1238104Sdes/*
2238104Sdes * util.c
3238104Sdes * some handy function needed in drill and not implemented
4238104Sdes * in ldns
5238104Sdes * (c) 2005 NLnet Labs
6238104Sdes *
7238104Sdes * See the file LICENSE for the license
8238104Sdes *
9238104Sdes */
10238104Sdes
11238104Sdes#include "drill.h"
12238104Sdes#include <ldns/ldns.h>
13238104Sdes
14238104Sdes#include <errno.h>
15238104Sdes
16246854Sdesstatic int
17238104Sdesread_line(FILE *input, char *line, size_t len)
18238104Sdes{
19246854Sdes	int i;
20269257Sdes	int c;
21269257Sdes
22246854Sdes	for (i = 0; i < (int)len-1; i++) {
23269257Sdes		c = getc(input);
24238104Sdes		if (c == EOF) {
25238104Sdes			return -1;
26238104Sdes		} else if (c != '\n') {
27238104Sdes			line[i] = c;
28238104Sdes		} else {
29238104Sdes			break;
30238104Sdes		}
31238104Sdes	}
32238104Sdes	line[i] = '\0';
33238104Sdes	return i;
34238104Sdes}
35238104Sdes
36238104Sdes/* key_list must be initialized with ldns_rr_list_new() */
37238104Sdesldns_status
38246854Sdesread_key_file(const char *filename, ldns_rr_list *key_list, bool silently)
39238104Sdes{
40238104Sdes	int line_len = 0;
41238104Sdes	int line_nr = 0;
42238104Sdes	int key_count = 0;
43246854Sdes	char line[LDNS_MAX_LINELEN];
44238104Sdes	ldns_status status;
45238104Sdes	FILE *input_file;
46238104Sdes	ldns_rr *rr;
47238104Sdes
48238104Sdes	input_file = fopen(filename, "r");
49238104Sdes	if (!input_file) {
50246854Sdes		if (! silently) {
51246854Sdes			fprintf(stderr, "Error opening %s: %s\n",
52246854Sdes				filename, strerror(errno));
53246854Sdes		}
54238104Sdes		return LDNS_STATUS_ERR;
55238104Sdes	}
56238104Sdes	while (line_len >= 0) {
57238104Sdes		line_len = (int) read_line(input_file, line, sizeof(line));
58238104Sdes		line_nr++;
59238104Sdes		if (line_len > 0 && line[0] != ';') {
60238104Sdes			status = ldns_rr_new_frm_str(&rr, line, 0, NULL, NULL);
61238104Sdes			if (status != LDNS_STATUS_OK) {
62246854Sdes				if (! silently) {
63246854Sdes					fprintf(stderr,
64246854Sdes						"Error parsing DNSKEY RR "
65246854Sdes						"in line %d: %s\n", line_nr,
66246854Sdes						ldns_get_errorstr_by_id(status)
67246854Sdes						);
68246854Sdes				}
69238104Sdes			} else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY ||
70238104Sdes					   ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) {
71238104Sdes				ldns_rr_list_push_rr(key_list, rr);
72238104Sdes				key_count++;
73238104Sdes			} else {
74238104Sdes				ldns_rr_free(rr);
75238104Sdes			}
76238104Sdes		}
77238104Sdes	}
78246854Sdes	fclose(input_file);
79238104Sdes	if (key_count > 0) {
80238104Sdes		return LDNS_STATUS_OK;
81238104Sdes	} else {
82238104Sdes		/*fprintf(stderr, "No keys read\n");*/
83238104Sdes		return LDNS_STATUS_ERR;
84238104Sdes	}
85238104Sdes}
86238104Sdes
87238104Sdesldns_rdf *
88238104Sdesldns_rdf_new_addr_frm_str(char *str)
89238104Sdes{
90238104Sdes	ldns_rdf *a;
91238104Sdes
92238104Sdes	a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, str);
93238104Sdes	if (!a) {
94238104Sdes		/* maybe ip6 */
95238104Sdes		a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, str);
96238104Sdes		if (!a) {
97238104Sdes			return NULL;
98238104Sdes		}
99238104Sdes	}
100238104Sdes	return a;
101238104Sdes}
102238104Sdes
103238104Sdesstatic inline void
104238104Sdeslocal_print_ds(FILE* out, const char* pre, ldns_rr* ds)
105238104Sdes{
106238104Sdes	if (out && ds) {
107238104Sdes		fprintf(out, "%s", pre);
108238104Sdes		ldns_rr_print(out, ds);
109238104Sdes		ldns_rr_free(ds);
110238104Sdes	}
111238104Sdes}
112238104Sdes
113238104Sdes/*
114238104Sdes * For all keys in a packet print the DS
115238104Sdes */
116238104Sdesvoid
117238104Sdesprint_ds_of_keys(ldns_pkt *p)
118238104Sdes{
119238104Sdes	ldns_rr_list *keys;
120238104Sdes	uint16_t i;
121238104Sdes	ldns_rr *ds;
122238104Sdes
123238104Sdes	/* TODO fix the section stuff, here or in ldns */
124238104Sdes	keys = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_DNSKEY,
125238104Sdes			LDNS_SECTION_ANSWER);
126238104Sdes
127238104Sdes	/* this also returns the question section rr, which does not
128238104Sdes	 * have any data.... and this inturn crashes everything */
129238104Sdes
130238104Sdes	if (keys) {
131238104Sdes		for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
132238104Sdes			fprintf(stdout, ";\n; equivalent DS records for key %u:\n",
133238104Sdes				(unsigned int)ldns_calc_keytag(ldns_rr_list_rr(keys, i)));
134238104Sdes
135238104Sdes			ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA1);
136238104Sdes			local_print_ds(stdout, "; sha1: ", ds);
137238104Sdes			ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA256);
138238104Sdes			local_print_ds(stdout, "; sha256: ", ds);
139238104Sdes		}
140246854Sdes		ldns_rr_list_deep_free(keys);
141238104Sdes	}
142238104Sdes}
143238104Sdes
144238104Sdesstatic void
145238104Sdesprint_class_type(FILE *fp, ldns_rr *r)
146238104Sdes{
147238104Sdes	ldns_lookup_table *lt;
148238104Sdes        lt = ldns_lookup_by_id(ldns_rr_classes, ldns_rr_get_class(r));
149238104Sdes        if (lt) {
150238104Sdes               	fprintf(fp, " %s", lt->name);
151238104Sdes        } else {
152238104Sdes        	fprintf(fp, " CLASS%d", ldns_rr_get_class(r));
153238104Sdes        }
154238104Sdes	/* okay not THE way - but the quickest */
155238104Sdes	switch (ldns_rr_get_type(r)) {
156238104Sdes		case LDNS_RR_TYPE_RRSIG:
157238104Sdes			fprintf(fp, " RRSIG ");
158238104Sdes			break;
159238104Sdes		case LDNS_RR_TYPE_DNSKEY:
160238104Sdes			fprintf(fp, " DNSKEY ");
161238104Sdes			break;
162238104Sdes		case LDNS_RR_TYPE_DS:
163238104Sdes			fprintf(fp, " DS ");
164238104Sdes			break;
165238104Sdes		default:
166238104Sdes			break;
167238104Sdes	}
168238104Sdes}
169238104Sdes
170238104Sdes
171238104Sdesvoid
172238104Sdesprint_ds_abbr(FILE *fp, ldns_rr *ds)
173238104Sdes{
174238104Sdes	if (!ds || (ldns_rr_get_type(ds) != LDNS_RR_TYPE_DS)) {
175238104Sdes		return;
176238104Sdes	}
177238104Sdes
178238104Sdes	ldns_rdf_print(fp, ldns_rr_owner(ds));
179238104Sdes	fprintf(fp, " %d", (int)ldns_rr_ttl(ds));
180238104Sdes	print_class_type(fp, ds);
181238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(ds, 0)); fprintf(fp, " ");
182238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(ds, 1)); fprintf(fp, " ");
183238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(ds, 2)); fprintf(fp, " ");
184238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(ds, 3)); fprintf(fp, " ");
185238104Sdes}
186238104Sdes
187238104Sdes/* print some of the elements of a signature */
188238104Sdesvoid
189238104Sdesprint_rrsig_abbr(FILE *fp, ldns_rr *sig) {
190238104Sdes	if (!sig || (ldns_rr_get_type(sig) != LDNS_RR_TYPE_RRSIG)) {
191238104Sdes		return;
192238104Sdes	}
193238104Sdes
194238104Sdes	ldns_rdf_print(fp, ldns_rr_owner(sig));
195238104Sdes	fprintf(fp, " %d", (int)ldns_rr_ttl(sig));
196238104Sdes	print_class_type(fp, sig);
197238104Sdes
198238104Sdes	/* print a number of rdf's */
199238104Sdes	/* typecovered */
200238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(sig, 0)); fprintf(fp, " ");
201238104Sdes	/* algo */
202238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(sig, 1)); fprintf(fp, " ");
203238104Sdes	/* labels */
204238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(sig, 2)); fprintf(fp, " (\n\t\t\t");
205238104Sdes	/* expir */
206238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(sig, 4)); fprintf(fp, " ");
207238104Sdes	/* incep */
208238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(sig, 5)); fprintf(fp, " ");
209238104Sdes	/* key-id */
210238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(sig, 6)); fprintf(fp, " ");
211238104Sdes	/* key owner */
212238104Sdes	ldns_rdf_print(fp, ldns_rr_rdf(sig, 7)); fprintf(fp, ")");
213238104Sdes}
214238104Sdes
215238104Sdesvoid
216238104Sdesprint_dnskey_abbr(FILE *fp, ldns_rr *key)
217238104Sdes{
218238104Sdes        if (!key || (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY)) {
219238104Sdes                return;
220238104Sdes        }
221238104Sdes
222238104Sdes        ldns_rdf_print(fp, ldns_rr_owner(key));
223238104Sdes        fprintf(fp, " %d", (int)ldns_rr_ttl(key));
224238104Sdes	print_class_type(fp, key);
225238104Sdes
226238104Sdes        /* print a number of rdf's */
227238104Sdes        /* flags */
228238104Sdes        ldns_rdf_print(fp, ldns_rr_rdf(key, 0)); fprintf(fp, " ");
229238104Sdes        /* proto */
230238104Sdes        ldns_rdf_print(fp, ldns_rr_rdf(key, 1)); fprintf(fp, " ");
231238104Sdes        /* algo */
232238104Sdes        ldns_rdf_print(fp, ldns_rr_rdf(key, 2));
233238104Sdes
234238104Sdes	if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 256) {
235238104Sdes		fprintf(fp, " ;{id = %u (zsk), size = %db}", (unsigned int)ldns_calc_keytag(key),
236238104Sdes				(int)ldns_rr_dnskey_key_size(key));
237238104Sdes		return;
238238104Sdes	}
239238104Sdes	if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 257) {
240238104Sdes		fprintf(fp, " ;{id = %u (ksk), size = %db}", (unsigned int)ldns_calc_keytag(key),
241238104Sdes				(int)ldns_rr_dnskey_key_size(key));
242238104Sdes		return;
243238104Sdes	}
244238104Sdes	fprintf(fp, " ;{id = %u, size = %db}", (unsigned int)ldns_calc_keytag(key),
245238104Sdes			(int)ldns_rr_dnskey_key_size(key));
246238104Sdes}
247238104Sdes
248238104Sdesvoid
249238104Sdesprint_rr_list_abbr(FILE *fp, ldns_rr_list *rrlist, const char *usr)
250238104Sdes{
251238104Sdes	size_t i;
252238104Sdes	ldns_rr_type tp;
253238104Sdes
254238104Sdes	for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
255238104Sdes		tp = ldns_rr_get_type(ldns_rr_list_rr(rrlist, i));
256238104Sdes		if (i == 0 && tp != LDNS_RR_TYPE_RRSIG) {
257238104Sdes			if (usr) {
258238104Sdes				fprintf(fp, "%s ", usr);
259238104Sdes			}
260238104Sdes		}
261238104Sdes		switch(tp) {
262238104Sdes		case LDNS_RR_TYPE_DNSKEY:
263238104Sdes			print_dnskey_abbr(fp, ldns_rr_list_rr(rrlist, i));
264238104Sdes			break;
265238104Sdes		case LDNS_RR_TYPE_RRSIG:
266238104Sdes			print_rrsig_abbr(fp, ldns_rr_list_rr(rrlist, i));
267238104Sdes			break;
268238104Sdes		case LDNS_RR_TYPE_DS:
269238104Sdes			print_ds_abbr(fp, ldns_rr_list_rr(rrlist, i));
270238104Sdes			break;
271238104Sdes		default:
272238104Sdes			/* not handled */
273238104Sdes			break;
274238104Sdes		}
275238104Sdes		fputs("\n", fp);
276238104Sdes	}
277238104Sdes}
278238104Sdes
279238104Sdesvoid *
280238104Sdesxmalloc(size_t s)
281238104Sdes{
282238104Sdes	void *p;
283238104Sdes
284238104Sdes	p = malloc(s);
285238104Sdes	if (!p) {
286238104Sdes		printf("Mem failure\n");
287238104Sdes		exit(EXIT_FAILURE);
288238104Sdes	}
289238104Sdes	return p;
290238104Sdes}
291238104Sdes
292238104Sdesvoid *
293238104Sdesxrealloc(void *p, size_t size)
294238104Sdes{
295238104Sdes	void *q;
296238104Sdes
297238104Sdes	q = realloc(p, size);
298238104Sdes	if (!q) {
299238104Sdes		printf("Mem failure\n");
300238104Sdes		exit(EXIT_FAILURE);
301238104Sdes	}
302238104Sdes	return q;
303238104Sdes}
304238104Sdes
305238104Sdesvoid
306238104Sdesxfree(void *p)
307238104Sdes{
308238104Sdes	if (p) {
309238104Sdes	        free(p);
310238104Sdes	}
311238104Sdes}
312