Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/ldns/higher.c
39475 views
1
/*
2
* higher.c
3
*
4
* Specify some higher level functions that would
5
* be useful 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
23
ldns_rr_list *
24
ldns_get_rr_list_addr_by_name(ldns_resolver *res, const ldns_rdf *name,
25
ldns_rr_class c, 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
106
ldns_rr_list *
107
ldns_get_rr_list_name_by_addr(ldns_resolver *res, const ldns_rdf *addr,
108
ldns_rr_class c, uint16_t flags)
109
{
110
ldns_pkt *pkt;
111
ldns_rr_list *names;
112
ldns_rdf *name;
113
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
ldns_rdf_deep_free(name);
130
if (pkt) {
131
/* extract the data we need */
132
names = ldns_pkt_rr_list_by_type(pkt,
133
LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER);
134
ldns_pkt_free(pkt);
135
}
136
return names;
137
}
138
139
/* read a line, put it in a buffer, parse the buffer */
140
ldns_rr_list *
141
ldns_get_rr_list_hosts_frm_fp(FILE *fp)
142
{
143
return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
144
}
145
146
ldns_rr_list *
147
ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
148
{
149
ssize_t i, j;
150
size_t cnt;
151
char *line;
152
char *word;
153
char *addr;
154
char *rr_str;
155
ldns_buffer *linebuf;
156
ldns_rr *rr;
157
ldns_rr_list *list;
158
ldns_rdf *tmp;
159
bool ip6;
160
ldns_status parse_result;
161
162
line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
163
word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
164
addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
165
rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
166
ip6 = false;
167
list = ldns_rr_list_new();
168
rr = NULL;
169
if(!line || !word || !addr || !rr_str || !list) {
170
LDNS_FREE(line);
171
LDNS_FREE(word);
172
LDNS_FREE(addr);
173
LDNS_FREE(rr_str);
174
ldns_rr_list_free(list);
175
return NULL;
176
}
177
178
for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
179
i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
180
/* # is comment */
181
if (line[0] == '#') {
182
continue;
183
}
184
/* put it in a buffer for further processing */
185
linebuf = LDNS_MALLOC(ldns_buffer);
186
if(!linebuf) {
187
LDNS_FREE(line);
188
LDNS_FREE(word);
189
LDNS_FREE(addr);
190
LDNS_FREE(rr_str);
191
ldns_rr_list_deep_free(list);
192
return NULL;
193
}
194
195
ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
196
for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
197
j > 0;
198
j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
199
if (cnt == 0) {
200
/* the address */
201
if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA,
202
word))) {
203
/* ip6 */
204
ldns_rdf_deep_free(tmp);
205
ip6 = true;
206
} else {
207
if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A,
208
word))) {
209
/* ip4 */
210
ldns_rdf_deep_free(tmp);
211
ip6 = false;
212
} else {
213
/* kaput */
214
break;
215
}
216
}
217
(void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
218
} else {
219
/* Stop parsing line when a comment begins. */
220
if (word[0] == '#')
221
break;
222
/* la al la la */
223
if (ip6) {
224
snprintf(rr_str, LDNS_MAX_LINELEN,
225
"%s IN AAAA %s", word, addr);
226
} else {
227
snprintf(rr_str, LDNS_MAX_LINELEN,
228
"%s IN A %s", word, addr);
229
}
230
parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
231
if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
232
ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
233
ldns_rr_free(rr);
234
}
235
}
236
}
237
ldns_buffer_free(linebuf);
238
}
239
LDNS_FREE(line);
240
LDNS_FREE(word);
241
LDNS_FREE(addr);
242
LDNS_FREE(rr_str);
243
return list;
244
}
245
246
ldns_rr_list *
247
ldns_get_rr_list_hosts_frm_file(char *filename)
248
{
249
ldns_rr_list *names;
250
FILE *fp;
251
252
if (!filename) {
253
fp = fopen(LDNS_RESOLV_HOSTS, "r");
254
255
} else {
256
fp = fopen(filename, "r");
257
}
258
if (!fp) {
259
return NULL;
260
}
261
262
names = ldns_get_rr_list_hosts_frm_fp(fp);
263
fclose(fp);
264
return names;
265
}
266
267
uint16_t
268
ldns_getaddrinfo(ldns_resolver *res, const ldns_rdf *node,
269
ldns_rr_class c, ldns_rr_list **ret)
270
{
271
ldns_rdf_type t;
272
uint16_t names_found;
273
ldns_resolver *r;
274
ldns_status s;
275
276
t = ldns_rdf_get_type(node);
277
names_found = 0;
278
r = res;
279
280
if (res == NULL) {
281
/* prepare a new resolver, using /etc/resolv.conf as a guide */
282
s = ldns_resolver_new_frm_file(&r, NULL);
283
if (s != LDNS_STATUS_OK) {
284
return 0;
285
}
286
}
287
288
if (t == LDNS_RDF_TYPE_DNAME) {
289
/* we're asked to query for a name */
290
*ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
291
names_found = ldns_rr_list_rr_count(*ret);
292
}
293
294
if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
295
/* an address */
296
*ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
297
names_found = ldns_rr_list_rr_count(*ret);
298
}
299
300
if (res == NULL) {
301
ldns_resolver_deep_free(r);
302
}
303
304
return names_found;
305
}
306
307
bool
308
ldns_nsec_type_check(const ldns_rr *nsec, ldns_rr_type t)
309
{
310
switch (ldns_rr_get_type(nsec)) {
311
case LDNS_RR_TYPE_NSEC : if (ldns_rr_rd_count(nsec) < 2) {
312
return false;
313
}
314
return ldns_nsec_bitmap_covers_type(
315
ldns_rr_rdf(nsec, 1), t);
316
317
case LDNS_RR_TYPE_NSEC3 : if (ldns_rr_rd_count(nsec) < 6) {
318
return false;
319
}
320
return ldns_nsec_bitmap_covers_type(
321
ldns_rr_rdf(nsec, 5), t);
322
323
default : return false;
324
}
325
}
326
327
void
328
ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
329
{
330
int16_t rdf;
331
ldns_rdf *rd;
332
va_list va_rdf;
333
va_start(va_rdf, rdfnum);
334
335
for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int))
336
{
337
rd = ldns_rr_rdf(r, rdf);
338
if (!rd) {
339
continue;
340
} else {
341
ldns_rdf_print(fp, rd);
342
fprintf(fp, " "); /* not sure if we want to do this */
343
}
344
}
345
va_end(va_rdf);
346
}
347
348
349