xref: /dflybsd-src/contrib/ldns/higher.c (revision d1b2b5caec9ab35b37f82c6e75b7f14f9c9103b2)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * higher.c
3825eb42bSJan Lentfer  *
4825eb42bSJan Lentfer  * Specify some higher level functions that would
5825eb42bSJan Lentfer  * be usefull to would be developers
6825eb42bSJan Lentfer  *
7825eb42bSJan Lentfer  * a Net::DNS like library for C
8825eb42bSJan Lentfer  *
9825eb42bSJan Lentfer  * (c) NLnet Labs, 2004-2006
10825eb42bSJan Lentfer  *
11825eb42bSJan Lentfer  * See the file LICENSE for the license
12825eb42bSJan Lentfer  */
13825eb42bSJan Lentfer 
14825eb42bSJan Lentfer #include <ldns/config.h>
15825eb42bSJan Lentfer 
16825eb42bSJan Lentfer #include <ldns/ldns.h>
17825eb42bSJan Lentfer 
18825eb42bSJan Lentfer #ifdef HAVE_SSL
19825eb42bSJan Lentfer #include <openssl/ssl.h>
20825eb42bSJan Lentfer #include <openssl/sha.h>
21825eb42bSJan Lentfer #endif /* HAVE_SSL */
22825eb42bSJan Lentfer 
23825eb42bSJan Lentfer ldns_rr_list *
24825eb42bSJan Lentfer ldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c,
25825eb42bSJan Lentfer 		uint16_t flags)
26825eb42bSJan Lentfer {
27825eb42bSJan Lentfer 	ldns_pkt *pkt;
28825eb42bSJan Lentfer 	ldns_rr_list *aaaa;
29825eb42bSJan Lentfer 	ldns_rr_list *a;
30825eb42bSJan Lentfer 	ldns_rr_list *result = NULL;
31825eb42bSJan Lentfer 	ldns_rr_list *hostsfilenames;
32825eb42bSJan Lentfer 	size_t i;
33825eb42bSJan Lentfer 	uint8_t ip6;
34825eb42bSJan Lentfer 
35825eb42bSJan Lentfer 	a = NULL;
36825eb42bSJan Lentfer 	aaaa = NULL;
37825eb42bSJan Lentfer 	result = NULL;
38825eb42bSJan Lentfer 
39825eb42bSJan Lentfer 	if (!res) {
40825eb42bSJan Lentfer 		return NULL;
41825eb42bSJan Lentfer 	}
42825eb42bSJan Lentfer 	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
43825eb42bSJan Lentfer 		return NULL;
44825eb42bSJan Lentfer 	}
45825eb42bSJan Lentfer 
46825eb42bSJan Lentfer 	ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save
47825eb42bSJan Lentfer 					 what was there */
48825eb42bSJan Lentfer 
49825eb42bSJan Lentfer 	ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY);
50825eb42bSJan Lentfer 
51825eb42bSJan Lentfer 	hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL);
52825eb42bSJan Lentfer 	for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) {
53825eb42bSJan Lentfer 		if (ldns_rdf_compare(name,
54825eb42bSJan Lentfer 					ldns_rr_owner(ldns_rr_list_rr(hostsfilenames,
55825eb42bSJan Lentfer 							i))) == 0) {
56825eb42bSJan Lentfer 			if (!result) {
57825eb42bSJan Lentfer 				result = ldns_rr_list_new();
58825eb42bSJan Lentfer 			}
59825eb42bSJan Lentfer 			ldns_rr_list_push_rr(result,
60825eb42bSJan Lentfer 					ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i)));
61825eb42bSJan Lentfer 		}
62825eb42bSJan Lentfer 	}
63825eb42bSJan Lentfer 	ldns_rr_list_deep_free(hostsfilenames);
64825eb42bSJan Lentfer 
65825eb42bSJan Lentfer 	if (result) {
66825eb42bSJan Lentfer 		return result;
67825eb42bSJan Lentfer 	}
68825eb42bSJan Lentfer 
69825eb42bSJan Lentfer 	/* add the RD flags, because we want an answer */
70825eb42bSJan Lentfer 	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD);
71825eb42bSJan Lentfer 	if (pkt) {
72825eb42bSJan Lentfer 		/* extract the data we need */
73825eb42bSJan Lentfer 		aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA,
74825eb42bSJan Lentfer 			LDNS_SECTION_ANSWER);
75825eb42bSJan Lentfer 		ldns_pkt_free(pkt);
76825eb42bSJan Lentfer 	}
77825eb42bSJan Lentfer 
78825eb42bSJan Lentfer 	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD);
79825eb42bSJan Lentfer 	if (pkt) {
80825eb42bSJan Lentfer 		/* extract the data we need */
81825eb42bSJan Lentfer 		a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER);
82825eb42bSJan Lentfer 		ldns_pkt_free(pkt);
83825eb42bSJan Lentfer 	}
84825eb42bSJan Lentfer 	ldns_resolver_set_ip6(res, ip6);
85825eb42bSJan Lentfer 
86825eb42bSJan Lentfer 	if (aaaa && a) {
87825eb42bSJan Lentfer 		result = ldns_rr_list_cat_clone(aaaa, a);
88825eb42bSJan Lentfer 		ldns_rr_list_deep_free(aaaa);
89825eb42bSJan Lentfer 		ldns_rr_list_deep_free(a);
90825eb42bSJan Lentfer 		return result;
91825eb42bSJan Lentfer 	}
92825eb42bSJan Lentfer 
93825eb42bSJan Lentfer 	if (aaaa) {
94825eb42bSJan Lentfer 		result = ldns_rr_list_clone(aaaa);
95825eb42bSJan Lentfer 	}
96825eb42bSJan Lentfer 
97825eb42bSJan Lentfer 	if (a) {
98825eb42bSJan Lentfer 		result = ldns_rr_list_clone(a);
99825eb42bSJan Lentfer 	}
100825eb42bSJan Lentfer 
101825eb42bSJan Lentfer 	ldns_rr_list_deep_free(aaaa);
102825eb42bSJan Lentfer 	ldns_rr_list_deep_free(a);
103825eb42bSJan Lentfer 	return result;
104825eb42bSJan Lentfer }
105825eb42bSJan Lentfer 
106825eb42bSJan Lentfer ldns_rr_list *
107825eb42bSJan Lentfer ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c,
108825eb42bSJan Lentfer 		uint16_t flags)
109825eb42bSJan Lentfer {
110825eb42bSJan Lentfer 	ldns_pkt *pkt;
111825eb42bSJan Lentfer 	ldns_rr_list *names;
112825eb42bSJan Lentfer 	ldns_rdf *name;
113825eb42bSJan Lentfer 
114825eb42bSJan Lentfer 	names = NULL;
115825eb42bSJan Lentfer 
116825eb42bSJan Lentfer 	if (!res || !addr) {
117825eb42bSJan Lentfer 		return NULL;
118825eb42bSJan Lentfer 	}
119825eb42bSJan Lentfer 
120825eb42bSJan Lentfer 	if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A &&
121825eb42bSJan Lentfer 			ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) {
122825eb42bSJan Lentfer 		return NULL;
123825eb42bSJan Lentfer 	}
124825eb42bSJan Lentfer 
125825eb42bSJan Lentfer 	name = ldns_rdf_address_reverse(addr);
126825eb42bSJan Lentfer 
127825eb42bSJan Lentfer 	/* add the RD flags, because we want an answer */
128825eb42bSJan Lentfer 	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD);
129*d1b2b5caSJohn Marino 	ldns_rdf_deep_free(name);
130825eb42bSJan Lentfer 	if (pkt) {
131825eb42bSJan Lentfer 		/* extract the data we need */
132825eb42bSJan Lentfer 		names = ldns_pkt_rr_list_by_type(pkt,
133825eb42bSJan Lentfer 				LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER);
134825eb42bSJan Lentfer 	}
135825eb42bSJan Lentfer 	return names;
136825eb42bSJan Lentfer }
137825eb42bSJan Lentfer 
138825eb42bSJan Lentfer /* read a line, put it in a buffer, parse the buffer */
139825eb42bSJan Lentfer ldns_rr_list *
140825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_fp(FILE *fp)
141825eb42bSJan Lentfer {
142825eb42bSJan Lentfer 	return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
143825eb42bSJan Lentfer }
144825eb42bSJan Lentfer 
145825eb42bSJan Lentfer ldns_rr_list *
146825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
147825eb42bSJan Lentfer {
148825eb42bSJan Lentfer 	ssize_t i, j;
149825eb42bSJan Lentfer 	size_t cnt;
150825eb42bSJan Lentfer 	char *line;
151825eb42bSJan Lentfer 	char *word;
152825eb42bSJan Lentfer 	char *addr;
153825eb42bSJan Lentfer 	char *rr_str;
154825eb42bSJan Lentfer 	ldns_buffer *linebuf;
155825eb42bSJan Lentfer 	ldns_rr *rr;
156825eb42bSJan Lentfer 	ldns_rr_list *list;
157825eb42bSJan Lentfer 	ldns_rdf *tmp;
158825eb42bSJan Lentfer 	bool ip6;
159825eb42bSJan Lentfer 	ldns_status parse_result;
160825eb42bSJan Lentfer 
161825eb42bSJan Lentfer 	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
162825eb42bSJan Lentfer 	word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
163825eb42bSJan Lentfer 	addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
164825eb42bSJan Lentfer 	rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
165825eb42bSJan Lentfer 	ip6 = false;
166825eb42bSJan Lentfer 	list = ldns_rr_list_new();
167825eb42bSJan Lentfer 	rr = NULL;
168ac996e71SJan Lentfer 	if(!line || !word || !addr || !rr_str || !list) {
169ac996e71SJan Lentfer 		LDNS_FREE(line);
170ac996e71SJan Lentfer 		LDNS_FREE(word);
171ac996e71SJan Lentfer 		LDNS_FREE(addr);
172ac996e71SJan Lentfer 		LDNS_FREE(rr_str);
173ac996e71SJan Lentfer 		ldns_rr_list_free(list);
174ac996e71SJan Lentfer 		return NULL;
175ac996e71SJan Lentfer 	}
176825eb42bSJan Lentfer 
177fd185f4dSJan Lentfer 	for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
178fd185f4dSJan Lentfer 			i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
179825eb42bSJan Lentfer 		/* # is comment */
180825eb42bSJan Lentfer 		if (line[0] == '#') {
181825eb42bSJan Lentfer 			continue;
182825eb42bSJan Lentfer 		}
183825eb42bSJan Lentfer 		/* put it in a buffer for further processing */
184825eb42bSJan Lentfer 		linebuf = LDNS_MALLOC(ldns_buffer);
185ac996e71SJan Lentfer 		if(!linebuf) {
186ac996e71SJan Lentfer 			LDNS_FREE(line);
187ac996e71SJan Lentfer 			LDNS_FREE(word);
188ac996e71SJan Lentfer 			LDNS_FREE(addr);
189ac996e71SJan Lentfer 			LDNS_FREE(rr_str);
190ac996e71SJan Lentfer 			ldns_rr_list_deep_free(list);
191ac996e71SJan Lentfer 			return NULL;
192ac996e71SJan Lentfer 		}
193825eb42bSJan Lentfer 
194825eb42bSJan Lentfer 		ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
195fd185f4dSJan Lentfer 		for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
196825eb42bSJan Lentfer 				j > 0;
197fd185f4dSJan Lentfer 				j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
198825eb42bSJan Lentfer 			if (cnt == 0) {
199825eb42bSJan Lentfer 				/* the address */
200825eb42bSJan Lentfer 				if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA,
201825eb42bSJan Lentfer 								word))) {
202825eb42bSJan Lentfer 					/* ip6 */
203825eb42bSJan Lentfer 					ldns_rdf_deep_free(tmp);
204825eb42bSJan Lentfer 					ip6 = true;
205825eb42bSJan Lentfer 				} else {
206825eb42bSJan Lentfer 					if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A,
207825eb42bSJan Lentfer 									word))) {
208825eb42bSJan Lentfer 						/* ip4 */
209825eb42bSJan Lentfer 						ldns_rdf_deep_free(tmp);
210825eb42bSJan Lentfer 						ip6 = false;
211825eb42bSJan Lentfer 					} else {
212825eb42bSJan Lentfer 						/* kaput */
213825eb42bSJan Lentfer 						break;
214825eb42bSJan Lentfer 					}
215825eb42bSJan Lentfer 				}
216fd185f4dSJan Lentfer 				(void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
217825eb42bSJan Lentfer 			} else {
218825eb42bSJan Lentfer 				/* la al la la */
219825eb42bSJan Lentfer 				if (ip6) {
220825eb42bSJan Lentfer 					snprintf(rr_str, LDNS_MAX_LINELEN,
221825eb42bSJan Lentfer 						"%s IN AAAA %s", word, addr);
222825eb42bSJan Lentfer 				} else {
223825eb42bSJan Lentfer 					snprintf(rr_str, LDNS_MAX_LINELEN,
224825eb42bSJan Lentfer 						"%s IN A %s", word, addr);
225825eb42bSJan Lentfer 				}
226825eb42bSJan Lentfer 				parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
227825eb42bSJan Lentfer 				if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
228825eb42bSJan Lentfer 					ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
229825eb42bSJan Lentfer 				}
230825eb42bSJan Lentfer 				ldns_rr_free(rr);
231825eb42bSJan Lentfer 			}
232825eb42bSJan Lentfer 		}
233825eb42bSJan Lentfer 		ldns_buffer_free(linebuf);
234825eb42bSJan Lentfer 	}
235825eb42bSJan Lentfer 	LDNS_FREE(line);
236825eb42bSJan Lentfer 	LDNS_FREE(word);
237825eb42bSJan Lentfer 	LDNS_FREE(addr);
238825eb42bSJan Lentfer 	LDNS_FREE(rr_str);
239825eb42bSJan Lentfer 	return list;
240825eb42bSJan Lentfer }
241825eb42bSJan Lentfer 
242825eb42bSJan Lentfer ldns_rr_list *
243825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_file(char *filename)
244825eb42bSJan Lentfer {
245825eb42bSJan Lentfer 	ldns_rr_list *names;
246825eb42bSJan Lentfer 	FILE *fp;
247825eb42bSJan Lentfer 
248825eb42bSJan Lentfer 	if (!filename) {
249825eb42bSJan Lentfer                 fp = fopen(LDNS_RESOLV_HOSTS, "r");
250825eb42bSJan Lentfer 
251825eb42bSJan Lentfer         } else {
252825eb42bSJan Lentfer                 fp = fopen(filename, "r");
253825eb42bSJan Lentfer         }
254825eb42bSJan Lentfer         if (!fp) {
255825eb42bSJan Lentfer                 return NULL;
256825eb42bSJan Lentfer         }
257825eb42bSJan Lentfer 
258825eb42bSJan Lentfer 	names = ldns_get_rr_list_hosts_frm_fp(fp);
259825eb42bSJan Lentfer 	fclose(fp);
260825eb42bSJan Lentfer 	return names;
261825eb42bSJan Lentfer }
262825eb42bSJan Lentfer 
263825eb42bSJan Lentfer uint16_t
264825eb42bSJan Lentfer ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c,
265825eb42bSJan Lentfer 		ldns_rr_list **ret)
266825eb42bSJan Lentfer {
267825eb42bSJan Lentfer 	ldns_rdf_type t;
268825eb42bSJan Lentfer 	uint16_t names_found;
269825eb42bSJan Lentfer 	ldns_resolver *r;
270825eb42bSJan Lentfer 	ldns_status s;
271825eb42bSJan Lentfer 
272825eb42bSJan Lentfer 	t = ldns_rdf_get_type(node);
273825eb42bSJan Lentfer 	names_found = 0;
274825eb42bSJan Lentfer 	r = res;
275825eb42bSJan Lentfer 
276825eb42bSJan Lentfer 	if (res == NULL) {
277825eb42bSJan Lentfer 		/* prepare a new resolver, using /etc/resolv.conf as a guide  */
278825eb42bSJan Lentfer 		s = ldns_resolver_new_frm_file(&r, NULL);
279825eb42bSJan Lentfer 		if (s != LDNS_STATUS_OK) {
280825eb42bSJan Lentfer 			return 0;
281825eb42bSJan Lentfer 		}
282825eb42bSJan Lentfer 	}
283825eb42bSJan Lentfer 
284825eb42bSJan Lentfer 	if (t == LDNS_RDF_TYPE_DNAME) {
285825eb42bSJan Lentfer 		/* we're asked to query for a name */
286825eb42bSJan Lentfer 		*ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
287825eb42bSJan Lentfer 		names_found = ldns_rr_list_rr_count(*ret);
288825eb42bSJan Lentfer 	}
289825eb42bSJan Lentfer 
290825eb42bSJan Lentfer 	if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
291825eb42bSJan Lentfer 		/* an address */
292825eb42bSJan Lentfer 		*ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
293825eb42bSJan Lentfer 		names_found = ldns_rr_list_rr_count(*ret);
294825eb42bSJan Lentfer 	}
295825eb42bSJan Lentfer 
296825eb42bSJan Lentfer 	if (res == NULL) {
297825eb42bSJan Lentfer 		ldns_resolver_deep_free(r);
298825eb42bSJan Lentfer 	}
299825eb42bSJan Lentfer 
300825eb42bSJan Lentfer 	return names_found;
301825eb42bSJan Lentfer }
302825eb42bSJan Lentfer 
303825eb42bSJan Lentfer bool
304825eb42bSJan Lentfer ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t)
305825eb42bSJan Lentfer {
306825eb42bSJan Lentfer 	/* does the nsec cover the t given? */
307825eb42bSJan Lentfer 	/* copied from host2str.c line 465: ldns_rdf2buffer_str_nsec */
308825eb42bSJan Lentfer         uint8_t window_block_nr;
309825eb42bSJan Lentfer         uint8_t bitmap_length;
310825eb42bSJan Lentfer         uint16_t type;
311825eb42bSJan Lentfer         uint16_t pos = 0;
312825eb42bSJan Lentfer         uint16_t bit_pos;
313825eb42bSJan Lentfer 	ldns_rdf *nsec_type_list = ldns_rr_rdf(nsec, 1);
314b5dedccaSJan Lentfer 	uint8_t *data;
315b5dedccaSJan Lentfer 
316b5dedccaSJan Lentfer 	if (nsec_type_list == NULL) {
317b5dedccaSJan Lentfer 		return false;
318b5dedccaSJan Lentfer 	}
319b5dedccaSJan Lentfer 	data  = ldns_rdf_data(nsec_type_list);
320825eb42bSJan Lentfer 
321825eb42bSJan Lentfer 	while(pos < ldns_rdf_size(nsec_type_list)) {
322825eb42bSJan Lentfer 		window_block_nr = data[pos];
323825eb42bSJan Lentfer 		bitmap_length = data[pos + 1];
324825eb42bSJan Lentfer 		pos += 2;
325825eb42bSJan Lentfer 
326825eb42bSJan Lentfer 		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
327825eb42bSJan Lentfer 			if (ldns_get_bit(&data[pos], bit_pos)) {
328825eb42bSJan Lentfer 				type = 256 * (uint16_t) window_block_nr + bit_pos;
329825eb42bSJan Lentfer 
330825eb42bSJan Lentfer 				if ((ldns_rr_type)type == t) {
331825eb42bSJan Lentfer 					/* we have a winner */
332825eb42bSJan Lentfer 					return true;
333825eb42bSJan Lentfer 				}
334825eb42bSJan Lentfer 			}
335825eb42bSJan Lentfer 		}
336825eb42bSJan Lentfer 		pos += (uint16_t) bitmap_length;
337825eb42bSJan Lentfer 	}
338825eb42bSJan Lentfer 	return false;
339825eb42bSJan Lentfer }
340825eb42bSJan Lentfer 
341825eb42bSJan Lentfer void
342825eb42bSJan Lentfer ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
343825eb42bSJan Lentfer {
344825eb42bSJan Lentfer 	int16_t rdf;
345825eb42bSJan Lentfer 	ldns_rdf *rd;
346825eb42bSJan Lentfer 	va_list va_rdf;
347825eb42bSJan Lentfer 	va_start(va_rdf, rdfnum);
348825eb42bSJan Lentfer 
349825eb42bSJan Lentfer 	for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int))
350825eb42bSJan Lentfer 	{
351825eb42bSJan Lentfer 		rd = ldns_rr_rdf(r, rdf);
352825eb42bSJan Lentfer 		if (!rd) {
353825eb42bSJan Lentfer 			continue;
354825eb42bSJan Lentfer 		} else {
355825eb42bSJan Lentfer 			ldns_rdf_print(fp, rd);
356825eb42bSJan Lentfer 			fprintf(fp, " "); /* not sure if we want to do this */
357825eb42bSJan Lentfer 		}
358825eb42bSJan Lentfer 	}
359825eb42bSJan Lentfer 	va_end(va_rdf);
360825eb42bSJan Lentfer }
361