ldns/drill: Update vendor branch to 1.6.9
[dragonfly.git] / contrib / ldns / higher.c
CommitLineData
825eb42b
JL
1/*
2 * higher.c
3 *
4 * Specify some higher level functions that would
5 * be usefull to would be developers
6 *
7 * a Net::DNS like library for C
8 *
9 * (c) NLnet Labs, 2004-2006
10 *
11 * See the file LICENSE for the license
12 */
13
14#include <ldns/config.h>
15
16#include <ldns/ldns.h>
17
18#ifdef HAVE_SSL
19#include <openssl/ssl.h>
20#include <openssl/sha.h>
21#endif /* HAVE_SSL */
22
23ldns_rr_list *
24ldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c,
25 uint16_t flags)
26{
27 ldns_pkt *pkt;
28 ldns_rr_list *aaaa;
29 ldns_rr_list *a;
30 ldns_rr_list *result = NULL;
31 ldns_rr_list *hostsfilenames;
32 size_t i;
33 uint8_t ip6;
34
35 a = NULL;
36 aaaa = NULL;
37 result = NULL;
38
39 if (!res) {
40 return NULL;
41 }
42 if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
43 return NULL;
44 }
45
46 ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save
47 what was there */
48
49 ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY);
50
51 hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL);
52 for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) {
53 if (ldns_rdf_compare(name,
54 ldns_rr_owner(ldns_rr_list_rr(hostsfilenames,
55 i))) == 0) {
56 if (!result) {
57 result = ldns_rr_list_new();
58 }
59 ldns_rr_list_push_rr(result,
60 ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i)));
61 }
62 }
63 ldns_rr_list_deep_free(hostsfilenames);
64
65 if (result) {
66 return result;
67 }
68
69 /* add the RD flags, because we want an answer */
70 pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD);
71 if (pkt) {
72 /* extract the data we need */
73 aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA,
74 LDNS_SECTION_ANSWER);
75 ldns_pkt_free(pkt);
76 }
77
78 pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD);
79 if (pkt) {
80 /* extract the data we need */
81 a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER);
82 ldns_pkt_free(pkt);
83 }
84 ldns_resolver_set_ip6(res, ip6);
85
86 if (aaaa && a) {
87 result = ldns_rr_list_cat_clone(aaaa, a);
88 ldns_rr_list_deep_free(aaaa);
89 ldns_rr_list_deep_free(a);
90 return result;
91 }
92
93 if (aaaa) {
94 result = ldns_rr_list_clone(aaaa);
95 }
96
97 if (a) {
98 result = ldns_rr_list_clone(a);
99 }
100
101 ldns_rr_list_deep_free(aaaa);
102 ldns_rr_list_deep_free(a);
103 return result;
104}
105
106ldns_rr_list *
107ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c,
108 uint16_t flags)
109{
110 ldns_pkt *pkt;
111 ldns_rr_list *names;
112 ldns_rdf *name;
825eb42b 113
825eb42b
JL
114 names = NULL;
115
116 if (!res || !addr) {
117 return NULL;
118 }
119
120 if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A &&
121 ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) {
122 return NULL;
123 }
124
125 name = ldns_rdf_address_reverse(addr);
126
127 /* add the RD flags, because we want an answer */
128 pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD);
129 if (pkt) {
130 /* extract the data we need */
131 names = ldns_pkt_rr_list_by_type(pkt,
132 LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER);
133 }
134 return names;
135}
136
137/* read a line, put it in a buffer, parse the buffer */
138ldns_rr_list *
139ldns_get_rr_list_hosts_frm_fp(FILE *fp)
140{
141 return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
142}
143
144ldns_rr_list *
145ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
146{
147 ssize_t i, j;
148 size_t cnt;
149 char *line;
150 char *word;
151 char *addr;
152 char *rr_str;
153 ldns_buffer *linebuf;
154 ldns_rr *rr;
155 ldns_rr_list *list;
156 ldns_rdf *tmp;
157 bool ip6;
158 ldns_status parse_result;
159
160 line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
161 word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
162 addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
163 rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
164 ip6 = false;
165 list = ldns_rr_list_new();
166 rr = NULL;
ac996e71
JL
167 if(!line || !word || !addr || !rr_str || !list) {
168 LDNS_FREE(line);
169 LDNS_FREE(word);
170 LDNS_FREE(addr);
171 LDNS_FREE(rr_str);
172 ldns_rr_list_free(list);
173 return NULL;
174 }
825eb42b 175
fd185f4d
JL
176 for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
177 i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
825eb42b
JL
178 /* # is comment */
179 if (line[0] == '#') {
180 continue;
181 }
182 /* put it in a buffer for further processing */
183 linebuf = LDNS_MALLOC(ldns_buffer);
ac996e71
JL
184 if(!linebuf) {
185 LDNS_FREE(line);
186 LDNS_FREE(word);
187 LDNS_FREE(addr);
188 LDNS_FREE(rr_str);
189 ldns_rr_list_deep_free(list);
190 return NULL;
191 }
825eb42b
JL
192
193 ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
fd185f4d 194 for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
825eb42b 195 j > 0;
fd185f4d 196 j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
825eb42b
JL
197 if (cnt == 0) {
198 /* the address */
199 if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA,
200 word))) {
201 /* ip6 */
202 ldns_rdf_deep_free(tmp);
203 ip6 = true;
204 } else {
205 if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A,
206 word))) {
207 /* ip4 */
208 ldns_rdf_deep_free(tmp);
209 ip6 = false;
210 } else {
211 /* kaput */
212 break;
213 }
214 }
fd185f4d 215 (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
825eb42b
JL
216 } else {
217 /* la al la la */
218 if (ip6) {
219 snprintf(rr_str, LDNS_MAX_LINELEN,
220 "%s IN AAAA %s", word, addr);
221 } else {
222 snprintf(rr_str, LDNS_MAX_LINELEN,
223 "%s IN A %s", word, addr);
224 }
225 parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
226 if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
227 ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
228 }
229 ldns_rr_free(rr);
230 }
231 }
232 ldns_buffer_free(linebuf);
233 }
234 LDNS_FREE(line);
235 LDNS_FREE(word);
236 LDNS_FREE(addr);
237 LDNS_FREE(rr_str);
238 return list;
239}
240
241ldns_rr_list *
242ldns_get_rr_list_hosts_frm_file(char *filename)
243{
244 ldns_rr_list *names;
245 FILE *fp;
246
247 if (!filename) {
248 fp = fopen(LDNS_RESOLV_HOSTS, "r");
249
250 } else {
251 fp = fopen(filename, "r");
252 }
253 if (!fp) {
254 return NULL;
255 }
256
257 names = ldns_get_rr_list_hosts_frm_fp(fp);
258 fclose(fp);
259 return names;
260}
261
262uint16_t
263ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c,
264 ldns_rr_list **ret)
265{
266 ldns_rdf_type t;
267 uint16_t names_found;
268 ldns_resolver *r;
269 ldns_status s;
270
271 t = ldns_rdf_get_type(node);
272 names_found = 0;
273 r = res;
274
275 if (res == NULL) {
276 /* prepare a new resolver, using /etc/resolv.conf as a guide */
277 s = ldns_resolver_new_frm_file(&r, NULL);
278 if (s != LDNS_STATUS_OK) {
279 return 0;
280 }
281 }
282
283 if (t == LDNS_RDF_TYPE_DNAME) {
284 /* we're asked to query for a name */
285 *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
286 names_found = ldns_rr_list_rr_count(*ret);
287 }
288
289 if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
290 /* an address */
291 *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
292 names_found = ldns_rr_list_rr_count(*ret);
293 }
294
295 if (res == NULL) {
296 ldns_resolver_deep_free(r);
297 }
298
299 return names_found;
300}
301
302bool
303ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t)
304{
305 /* does the nsec cover the t given? */
306 /* copied from host2str.c line 465: ldns_rdf2buffer_str_nsec */
307 uint8_t window_block_nr;
308 uint8_t bitmap_length;
309 uint16_t type;
310 uint16_t pos = 0;
311 uint16_t bit_pos;
312 ldns_rdf *nsec_type_list = ldns_rr_rdf(nsec, 1);
313 uint8_t *data = ldns_rdf_data(nsec_type_list);
314
315 while(pos < ldns_rdf_size(nsec_type_list)) {
316 window_block_nr = data[pos];
317 bitmap_length = data[pos + 1];
318 pos += 2;
319
320 for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
321 if (ldns_get_bit(&data[pos], bit_pos)) {
322 type = 256 * (uint16_t) window_block_nr + bit_pos;
323
324 if ((ldns_rr_type)type == t) {
325 /* we have a winner */
326 return true;
327 }
328 }
329 }
330 pos += (uint16_t) bitmap_length;
331 }
332 return false;
333}
334
335void
336ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
337{
338 int16_t rdf;
339 ldns_rdf *rd;
340 va_list va_rdf;
341 va_start(va_rdf, rdfnum);
342
343 for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int))
344 {
345 rd = ldns_rr_rdf(r, rdf);
346 if (!rd) {
347 continue;
348 } else {
349 ldns_rdf_print(fp, rd);
350 fprintf(fp, " "); /* not sure if we want to do this */
351 }
352 }
353 va_end(va_rdf);
354}