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 23 ldns_rr_list * 24 ldns_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 106 ldns_rr_list * 107 ldns_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; 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 } 135 return names; 136 } 137 138 /* read a line, put it in a buffer, parse the buffer */ 139 ldns_rr_list * 140 ldns_get_rr_list_hosts_frm_fp(FILE *fp) 141 { 142 return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL); 143 } 144 145 ldns_rr_list * 146 ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) 147 { 148 ssize_t i, j; 149 size_t cnt; 150 char *line; 151 char *word; 152 char *addr; 153 char *rr_str; 154 ldns_buffer *linebuf; 155 ldns_rr *rr; 156 ldns_rr_list *list; 157 ldns_rdf *tmp; 158 bool ip6; 159 ldns_status parse_result; 160 161 line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 162 word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 163 addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 164 rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 165 ip6 = false; 166 list = ldns_rr_list_new(); 167 rr = NULL; 168 if(!line || !word || !addr || !rr_str || !list) { 169 LDNS_FREE(line); 170 LDNS_FREE(word); 171 LDNS_FREE(addr); 172 LDNS_FREE(rr_str); 173 ldns_rr_list_free(list); 174 return NULL; 175 } 176 177 for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr); 178 i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) { 179 /* # is comment */ 180 if (line[0] == '#') { 181 continue; 182 } 183 /* put it in a buffer for further processing */ 184 linebuf = LDNS_MALLOC(ldns_buffer); 185 if(!linebuf) { 186 LDNS_FREE(line); 187 LDNS_FREE(word); 188 LDNS_FREE(addr); 189 LDNS_FREE(rr_str); 190 ldns_rr_list_deep_free(list); 191 return NULL; 192 } 193 194 ldns_buffer_new_frm_data(linebuf, line, (size_t) i); 195 for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN); 196 j > 0; 197 j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) { 198 if (cnt == 0) { 199 /* the address */ 200 if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 201 word))) { 202 /* ip6 */ 203 ldns_rdf_deep_free(tmp); 204 ip6 = true; 205 } else { 206 if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 207 word))) { 208 /* ip4 */ 209 ldns_rdf_deep_free(tmp); 210 ip6 = false; 211 } else { 212 /* kaput */ 213 break; 214 } 215 } 216 (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1); 217 } else { 218 /* la al la la */ 219 if (ip6) { 220 snprintf(rr_str, LDNS_MAX_LINELEN, 221 "%s IN AAAA %s", word, addr); 222 } else { 223 snprintf(rr_str, LDNS_MAX_LINELEN, 224 "%s IN A %s", word, addr); 225 } 226 parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL); 227 if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) { 228 ldns_rr_list_push_rr(list, ldns_rr_clone(rr)); 229 } 230 ldns_rr_free(rr); 231 } 232 } 233 ldns_buffer_free(linebuf); 234 } 235 LDNS_FREE(line); 236 LDNS_FREE(word); 237 LDNS_FREE(addr); 238 LDNS_FREE(rr_str); 239 return list; 240 } 241 242 ldns_rr_list * 243 ldns_get_rr_list_hosts_frm_file(char *filename) 244 { 245 ldns_rr_list *names; 246 FILE *fp; 247 248 if (!filename) { 249 fp = fopen(LDNS_RESOLV_HOSTS, "r"); 250 251 } else { 252 fp = fopen(filename, "r"); 253 } 254 if (!fp) { 255 return NULL; 256 } 257 258 names = ldns_get_rr_list_hosts_frm_fp(fp); 259 fclose(fp); 260 return names; 261 } 262 263 uint16_t 264 ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 265 ldns_rr_list **ret) 266 { 267 ldns_rdf_type t; 268 uint16_t names_found; 269 ldns_resolver *r; 270 ldns_status s; 271 272 t = ldns_rdf_get_type(node); 273 names_found = 0; 274 r = res; 275 276 if (res == NULL) { 277 /* prepare a new resolver, using /etc/resolv.conf as a guide */ 278 s = ldns_resolver_new_frm_file(&r, NULL); 279 if (s != LDNS_STATUS_OK) { 280 return 0; 281 } 282 } 283 284 if (t == LDNS_RDF_TYPE_DNAME) { 285 /* we're asked to query for a name */ 286 *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0); 287 names_found = ldns_rr_list_rr_count(*ret); 288 } 289 290 if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) { 291 /* an address */ 292 *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0); 293 names_found = ldns_rr_list_rr_count(*ret); 294 } 295 296 if (res == NULL) { 297 ldns_resolver_deep_free(r); 298 } 299 300 return names_found; 301 } 302 303 bool 304 ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t) 305 { 306 /* does the nsec cover the t given? */ 307 /* copied from host2str.c line 465: ldns_rdf2buffer_str_nsec */ 308 uint8_t window_block_nr; 309 uint8_t bitmap_length; 310 uint16_t type; 311 uint16_t pos = 0; 312 uint16_t bit_pos; 313 ldns_rdf *nsec_type_list = ldns_rr_rdf(nsec, 1); 314 uint8_t *data; 315 316 if (nsec_type_list == NULL) { 317 return false; 318 } 319 data = ldns_rdf_data(nsec_type_list); 320 321 while(pos < ldns_rdf_size(nsec_type_list)) { 322 window_block_nr = data[pos]; 323 bitmap_length = data[pos + 1]; 324 pos += 2; 325 326 for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) { 327 if (ldns_get_bit(&data[pos], bit_pos)) { 328 type = 256 * (uint16_t) window_block_nr + bit_pos; 329 330 if ((ldns_rr_type)type == t) { 331 /* we have a winner */ 332 return true; 333 } 334 } 335 } 336 pos += (uint16_t) bitmap_length; 337 } 338 return false; 339 } 340 341 void 342 ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...) 343 { 344 int16_t rdf; 345 ldns_rdf *rd; 346 va_list va_rdf; 347 va_start(va_rdf, rdfnum); 348 349 for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 350 { 351 rd = ldns_rr_rdf(r, rdf); 352 if (!rd) { 353 continue; 354 } else { 355 ldns_rdf_print(fp, rd); 356 fprintf(fp, " "); /* not sure if we want to do this */ 357 } 358 } 359 va_end(va_rdf); 360 } 361