1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer * higher.c
3825eb42bSJan Lentfer *
4825eb42bSJan Lentfer * Specify some higher level functions that would
5*5340022aSzrj * be useful 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 *
ldns_get_rr_list_addr_by_name(ldns_resolver * res,const ldns_rdf * name,ldns_rr_class c,uint16_t flags)24*5340022aSzrj ldns_get_rr_list_addr_by_name(ldns_resolver *res, const ldns_rdf *name,
25*5340022aSzrj ldns_rr_class c, 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 *
ldns_get_rr_list_name_by_addr(ldns_resolver * res,const ldns_rdf * addr,ldns_rr_class c,uint16_t flags)107*5340022aSzrj ldns_get_rr_list_name_by_addr(ldns_resolver *res, const ldns_rdf *addr,
108*5340022aSzrj ldns_rr_class c, 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);
129d1b2b5caSJohn 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);
134*5340022aSzrj ldns_pkt_free(pkt);
135825eb42bSJan Lentfer }
136825eb42bSJan Lentfer return names;
137825eb42bSJan Lentfer }
138825eb42bSJan Lentfer
139825eb42bSJan Lentfer /* read a line, put it in a buffer, parse the buffer */
140825eb42bSJan Lentfer ldns_rr_list *
ldns_get_rr_list_hosts_frm_fp(FILE * fp)141825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_fp(FILE *fp)
142825eb42bSJan Lentfer {
143825eb42bSJan Lentfer return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
144825eb42bSJan Lentfer }
145825eb42bSJan Lentfer
146825eb42bSJan Lentfer ldns_rr_list *
ldns_get_rr_list_hosts_frm_fp_l(FILE * fp,int * line_nr)147825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
148825eb42bSJan Lentfer {
149825eb42bSJan Lentfer ssize_t i, j;
150825eb42bSJan Lentfer size_t cnt;
151825eb42bSJan Lentfer char *line;
152825eb42bSJan Lentfer char *word;
153825eb42bSJan Lentfer char *addr;
154825eb42bSJan Lentfer char *rr_str;
155825eb42bSJan Lentfer ldns_buffer *linebuf;
156825eb42bSJan Lentfer ldns_rr *rr;
157825eb42bSJan Lentfer ldns_rr_list *list;
158825eb42bSJan Lentfer ldns_rdf *tmp;
159825eb42bSJan Lentfer bool ip6;
160825eb42bSJan Lentfer ldns_status parse_result;
161825eb42bSJan Lentfer
162825eb42bSJan Lentfer line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
163825eb42bSJan Lentfer word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
164825eb42bSJan Lentfer addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
165825eb42bSJan Lentfer rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
166825eb42bSJan Lentfer ip6 = false;
167825eb42bSJan Lentfer list = ldns_rr_list_new();
168825eb42bSJan Lentfer rr = NULL;
169ac996e71SJan Lentfer if(!line || !word || !addr || !rr_str || !list) {
170ac996e71SJan Lentfer LDNS_FREE(line);
171ac996e71SJan Lentfer LDNS_FREE(word);
172ac996e71SJan Lentfer LDNS_FREE(addr);
173ac996e71SJan Lentfer LDNS_FREE(rr_str);
174ac996e71SJan Lentfer ldns_rr_list_free(list);
175ac996e71SJan Lentfer return NULL;
176ac996e71SJan Lentfer }
177825eb42bSJan Lentfer
178fd185f4dSJan Lentfer for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
179fd185f4dSJan Lentfer i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
180825eb42bSJan Lentfer /* # is comment */
181825eb42bSJan Lentfer if (line[0] == '#') {
182825eb42bSJan Lentfer continue;
183825eb42bSJan Lentfer }
184825eb42bSJan Lentfer /* put it in a buffer for further processing */
185825eb42bSJan Lentfer linebuf = LDNS_MALLOC(ldns_buffer);
186ac996e71SJan Lentfer if(!linebuf) {
187ac996e71SJan Lentfer LDNS_FREE(line);
188ac996e71SJan Lentfer LDNS_FREE(word);
189ac996e71SJan Lentfer LDNS_FREE(addr);
190ac996e71SJan Lentfer LDNS_FREE(rr_str);
191ac996e71SJan Lentfer ldns_rr_list_deep_free(list);
192ac996e71SJan Lentfer return NULL;
193ac996e71SJan Lentfer }
194825eb42bSJan Lentfer
195825eb42bSJan Lentfer ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
196fd185f4dSJan Lentfer for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
197825eb42bSJan Lentfer j > 0;
198fd185f4dSJan Lentfer j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
199825eb42bSJan Lentfer if (cnt == 0) {
200825eb42bSJan Lentfer /* the address */
201825eb42bSJan Lentfer if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA,
202825eb42bSJan Lentfer word))) {
203825eb42bSJan Lentfer /* ip6 */
204825eb42bSJan Lentfer ldns_rdf_deep_free(tmp);
205825eb42bSJan Lentfer ip6 = true;
206825eb42bSJan Lentfer } else {
207825eb42bSJan Lentfer if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A,
208825eb42bSJan Lentfer word))) {
209825eb42bSJan Lentfer /* ip4 */
210825eb42bSJan Lentfer ldns_rdf_deep_free(tmp);
211825eb42bSJan Lentfer ip6 = false;
212825eb42bSJan Lentfer } else {
213825eb42bSJan Lentfer /* kaput */
214825eb42bSJan Lentfer break;
215825eb42bSJan Lentfer }
216825eb42bSJan Lentfer }
217fd185f4dSJan Lentfer (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
218825eb42bSJan Lentfer } else {
219*5340022aSzrj /* Stop parsing line when a comment begins. */
220*5340022aSzrj if (word[0] == '#')
221*5340022aSzrj break;
222825eb42bSJan Lentfer /* la al la la */
223825eb42bSJan Lentfer if (ip6) {
224825eb42bSJan Lentfer snprintf(rr_str, LDNS_MAX_LINELEN,
225825eb42bSJan Lentfer "%s IN AAAA %s", word, addr);
226825eb42bSJan Lentfer } else {
227825eb42bSJan Lentfer snprintf(rr_str, LDNS_MAX_LINELEN,
228825eb42bSJan Lentfer "%s IN A %s", word, addr);
229825eb42bSJan Lentfer }
230825eb42bSJan Lentfer parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
231825eb42bSJan Lentfer if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
232825eb42bSJan Lentfer ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
233825eb42bSJan Lentfer ldns_rr_free(rr);
234825eb42bSJan Lentfer }
235825eb42bSJan Lentfer }
236*5340022aSzrj }
237825eb42bSJan Lentfer ldns_buffer_free(linebuf);
238825eb42bSJan Lentfer }
239825eb42bSJan Lentfer LDNS_FREE(line);
240825eb42bSJan Lentfer LDNS_FREE(word);
241825eb42bSJan Lentfer LDNS_FREE(addr);
242825eb42bSJan Lentfer LDNS_FREE(rr_str);
243825eb42bSJan Lentfer return list;
244825eb42bSJan Lentfer }
245825eb42bSJan Lentfer
246825eb42bSJan Lentfer ldns_rr_list *
ldns_get_rr_list_hosts_frm_file(char * filename)247825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_file(char *filename)
248825eb42bSJan Lentfer {
249825eb42bSJan Lentfer ldns_rr_list *names;
250825eb42bSJan Lentfer FILE *fp;
251825eb42bSJan Lentfer
252825eb42bSJan Lentfer if (!filename) {
253825eb42bSJan Lentfer fp = fopen(LDNS_RESOLV_HOSTS, "r");
254825eb42bSJan Lentfer
255825eb42bSJan Lentfer } else {
256825eb42bSJan Lentfer fp = fopen(filename, "r");
257825eb42bSJan Lentfer }
258825eb42bSJan Lentfer if (!fp) {
259825eb42bSJan Lentfer return NULL;
260825eb42bSJan Lentfer }
261825eb42bSJan Lentfer
262825eb42bSJan Lentfer names = ldns_get_rr_list_hosts_frm_fp(fp);
263825eb42bSJan Lentfer fclose(fp);
264825eb42bSJan Lentfer return names;
265825eb42bSJan Lentfer }
266825eb42bSJan Lentfer
267825eb42bSJan Lentfer uint16_t
ldns_getaddrinfo(ldns_resolver * res,const ldns_rdf * node,ldns_rr_class c,ldns_rr_list ** ret)268*5340022aSzrj ldns_getaddrinfo(ldns_resolver *res, const ldns_rdf *node,
269*5340022aSzrj ldns_rr_class c, ldns_rr_list **ret)
270825eb42bSJan Lentfer {
271825eb42bSJan Lentfer ldns_rdf_type t;
272825eb42bSJan Lentfer uint16_t names_found;
273825eb42bSJan Lentfer ldns_resolver *r;
274825eb42bSJan Lentfer ldns_status s;
275825eb42bSJan Lentfer
276825eb42bSJan Lentfer t = ldns_rdf_get_type(node);
277825eb42bSJan Lentfer names_found = 0;
278825eb42bSJan Lentfer r = res;
279825eb42bSJan Lentfer
280825eb42bSJan Lentfer if (res == NULL) {
281825eb42bSJan Lentfer /* prepare a new resolver, using /etc/resolv.conf as a guide */
282825eb42bSJan Lentfer s = ldns_resolver_new_frm_file(&r, NULL);
283825eb42bSJan Lentfer if (s != LDNS_STATUS_OK) {
284825eb42bSJan Lentfer return 0;
285825eb42bSJan Lentfer }
286825eb42bSJan Lentfer }
287825eb42bSJan Lentfer
288825eb42bSJan Lentfer if (t == LDNS_RDF_TYPE_DNAME) {
289825eb42bSJan Lentfer /* we're asked to query for a name */
290825eb42bSJan Lentfer *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
291825eb42bSJan Lentfer names_found = ldns_rr_list_rr_count(*ret);
292825eb42bSJan Lentfer }
293825eb42bSJan Lentfer
294825eb42bSJan Lentfer if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
295825eb42bSJan Lentfer /* an address */
296825eb42bSJan Lentfer *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
297825eb42bSJan Lentfer names_found = ldns_rr_list_rr_count(*ret);
298825eb42bSJan Lentfer }
299825eb42bSJan Lentfer
300825eb42bSJan Lentfer if (res == NULL) {
301825eb42bSJan Lentfer ldns_resolver_deep_free(r);
302825eb42bSJan Lentfer }
303825eb42bSJan Lentfer
304825eb42bSJan Lentfer return names_found;
305825eb42bSJan Lentfer }
306825eb42bSJan Lentfer
307825eb42bSJan Lentfer bool
ldns_nsec_type_check(const ldns_rr * nsec,ldns_rr_type t)308*5340022aSzrj ldns_nsec_type_check(const ldns_rr *nsec, ldns_rr_type t)
309825eb42bSJan Lentfer {
310*5340022aSzrj switch (ldns_rr_get_type(nsec)) {
311*5340022aSzrj case LDNS_RR_TYPE_NSEC : if (ldns_rr_rd_count(nsec) < 2) {
312b5dedccaSJan Lentfer return false;
313b5dedccaSJan Lentfer }
314*5340022aSzrj return ldns_nsec_bitmap_covers_type(
315*5340022aSzrj ldns_rr_rdf(nsec, 1), t);
316825eb42bSJan Lentfer
317*5340022aSzrj case LDNS_RR_TYPE_NSEC3 : if (ldns_rr_rd_count(nsec) < 6) {
318825eb42bSJan Lentfer return false;
319825eb42bSJan Lentfer }
320*5340022aSzrj return ldns_nsec_bitmap_covers_type(
321*5340022aSzrj ldns_rr_rdf(nsec, 5), t);
322*5340022aSzrj
323*5340022aSzrj default : return false;
324*5340022aSzrj }
325*5340022aSzrj }
326825eb42bSJan Lentfer
327825eb42bSJan Lentfer void
ldns_print_rr_rdf(FILE * fp,ldns_rr * r,int rdfnum,...)328825eb42bSJan Lentfer ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
329825eb42bSJan Lentfer {
330825eb42bSJan Lentfer int16_t rdf;
331825eb42bSJan Lentfer ldns_rdf *rd;
332825eb42bSJan Lentfer va_list va_rdf;
333825eb42bSJan Lentfer va_start(va_rdf, rdfnum);
334825eb42bSJan Lentfer
335825eb42bSJan Lentfer for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int))
336825eb42bSJan Lentfer {
337825eb42bSJan Lentfer rd = ldns_rr_rdf(r, rdf);
338825eb42bSJan Lentfer if (!rd) {
339825eb42bSJan Lentfer continue;
340825eb42bSJan Lentfer } else {
341825eb42bSJan Lentfer ldns_rdf_print(fp, rd);
342825eb42bSJan Lentfer fprintf(fp, " "); /* not sure if we want to do this */
343825eb42bSJan Lentfer }
344825eb42bSJan Lentfer }
345825eb42bSJan Lentfer va_end(va_rdf);
346825eb42bSJan Lentfer }
347*5340022aSzrj
348