1238104Sdes/* 2238104Sdes * higher.c 3238104Sdes * 4238104Sdes * Specify some higher level functions that would 5238104Sdes * be usefull to would be developers 6238104Sdes * 7238104Sdes * a Net::DNS like library for C 8238104Sdes * 9238104Sdes * (c) NLnet Labs, 2004-2006 10238104Sdes * 11238104Sdes * See the file LICENSE for the license 12238104Sdes */ 13238104Sdes 14238104Sdes#include <ldns/config.h> 15238104Sdes 16238104Sdes#include <ldns/ldns.h> 17238104Sdes 18238104Sdes#ifdef HAVE_SSL 19238104Sdes#include <openssl/ssl.h> 20238104Sdes#include <openssl/sha.h> 21238104Sdes#endif /* HAVE_SSL */ 22238104Sdes 23238104Sdesldns_rr_list * 24238104Sdesldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c, 25238104Sdes uint16_t flags) 26238104Sdes{ 27238104Sdes ldns_pkt *pkt; 28238104Sdes ldns_rr_list *aaaa; 29238104Sdes ldns_rr_list *a; 30238104Sdes ldns_rr_list *result = NULL; 31238104Sdes ldns_rr_list *hostsfilenames; 32238104Sdes size_t i; 33238104Sdes uint8_t ip6; 34238104Sdes 35238104Sdes a = NULL; 36238104Sdes aaaa = NULL; 37238104Sdes result = NULL; 38238104Sdes 39238104Sdes if (!res) { 40238104Sdes return NULL; 41238104Sdes } 42238104Sdes if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { 43238104Sdes return NULL; 44238104Sdes } 45238104Sdes 46238104Sdes ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save 47238104Sdes what was there */ 48238104Sdes 49238104Sdes ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY); 50238104Sdes 51238104Sdes hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL); 52238104Sdes for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) { 53238104Sdes if (ldns_rdf_compare(name, 54238104Sdes ldns_rr_owner(ldns_rr_list_rr(hostsfilenames, 55238104Sdes i))) == 0) { 56238104Sdes if (!result) { 57238104Sdes result = ldns_rr_list_new(); 58238104Sdes } 59238104Sdes ldns_rr_list_push_rr(result, 60238104Sdes ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i))); 61238104Sdes } 62238104Sdes } 63238104Sdes ldns_rr_list_deep_free(hostsfilenames); 64238104Sdes 65238104Sdes if (result) { 66238104Sdes return result; 67238104Sdes } 68238104Sdes 69238104Sdes /* add the RD flags, because we want an answer */ 70238104Sdes pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD); 71238104Sdes if (pkt) { 72238104Sdes /* extract the data we need */ 73238104Sdes aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA, 74238104Sdes LDNS_SECTION_ANSWER); 75238104Sdes ldns_pkt_free(pkt); 76238104Sdes } 77238104Sdes 78238104Sdes pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD); 79238104Sdes if (pkt) { 80238104Sdes /* extract the data we need */ 81238104Sdes a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER); 82238104Sdes ldns_pkt_free(pkt); 83238104Sdes } 84238104Sdes ldns_resolver_set_ip6(res, ip6); 85238104Sdes 86238104Sdes if (aaaa && a) { 87238104Sdes result = ldns_rr_list_cat_clone(aaaa, a); 88238104Sdes ldns_rr_list_deep_free(aaaa); 89238104Sdes ldns_rr_list_deep_free(a); 90238104Sdes return result; 91238104Sdes } 92238104Sdes 93238104Sdes if (aaaa) { 94238104Sdes result = ldns_rr_list_clone(aaaa); 95238104Sdes } 96238104Sdes 97238104Sdes if (a) { 98238104Sdes result = ldns_rr_list_clone(a); 99238104Sdes } 100238104Sdes 101238104Sdes ldns_rr_list_deep_free(aaaa); 102238104Sdes ldns_rr_list_deep_free(a); 103238104Sdes return result; 104238104Sdes} 105238104Sdes 106238104Sdesldns_rr_list * 107238104Sdesldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c, 108238104Sdes uint16_t flags) 109238104Sdes{ 110238104Sdes ldns_pkt *pkt; 111238104Sdes ldns_rr_list *names; 112238104Sdes ldns_rdf *name; 113238104Sdes 114238104Sdes names = NULL; 115238104Sdes 116238104Sdes if (!res || !addr) { 117238104Sdes return NULL; 118238104Sdes } 119238104Sdes 120238104Sdes if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A && 121238104Sdes ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) { 122238104Sdes return NULL; 123238104Sdes } 124238104Sdes 125238104Sdes name = ldns_rdf_address_reverse(addr); 126238104Sdes 127238104Sdes /* add the RD flags, because we want an answer */ 128238104Sdes pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD); 129246854Sdes ldns_rdf_deep_free(name); 130238104Sdes if (pkt) { 131238104Sdes /* extract the data we need */ 132238104Sdes names = ldns_pkt_rr_list_by_type(pkt, 133238104Sdes LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER); 134269257Sdes ldns_pkt_free(pkt); 135238104Sdes } 136238104Sdes return names; 137238104Sdes} 138238104Sdes 139238104Sdes/* read a line, put it in a buffer, parse the buffer */ 140238104Sdesldns_rr_list * 141238104Sdesldns_get_rr_list_hosts_frm_fp(FILE *fp) 142238104Sdes{ 143238104Sdes return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL); 144238104Sdes} 145238104Sdes 146238104Sdesldns_rr_list * 147238104Sdesldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) 148238104Sdes{ 149238104Sdes ssize_t i, j; 150238104Sdes size_t cnt; 151238104Sdes char *line; 152238104Sdes char *word; 153238104Sdes char *addr; 154238104Sdes char *rr_str; 155238104Sdes ldns_buffer *linebuf; 156238104Sdes ldns_rr *rr; 157238104Sdes ldns_rr_list *list; 158238104Sdes ldns_rdf *tmp; 159238104Sdes bool ip6; 160238104Sdes ldns_status parse_result; 161238104Sdes 162238104Sdes line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 163238104Sdes word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 164238104Sdes addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 165238104Sdes rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 166238104Sdes ip6 = false; 167238104Sdes list = ldns_rr_list_new(); 168238104Sdes rr = NULL; 169238104Sdes if(!line || !word || !addr || !rr_str || !list) { 170238104Sdes LDNS_FREE(line); 171238104Sdes LDNS_FREE(word); 172238104Sdes LDNS_FREE(addr); 173238104Sdes LDNS_FREE(rr_str); 174238104Sdes ldns_rr_list_free(list); 175238104Sdes return NULL; 176238104Sdes } 177238104Sdes 178238104Sdes for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr); 179238104Sdes i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) { 180238104Sdes /* # is comment */ 181238104Sdes if (line[0] == '#') { 182238104Sdes continue; 183238104Sdes } 184238104Sdes /* put it in a buffer for further processing */ 185238104Sdes linebuf = LDNS_MALLOC(ldns_buffer); 186238104Sdes if(!linebuf) { 187238104Sdes LDNS_FREE(line); 188238104Sdes LDNS_FREE(word); 189238104Sdes LDNS_FREE(addr); 190238104Sdes LDNS_FREE(rr_str); 191238104Sdes ldns_rr_list_deep_free(list); 192238104Sdes return NULL; 193238104Sdes } 194238104Sdes 195238104Sdes ldns_buffer_new_frm_data(linebuf, line, (size_t) i); 196238104Sdes for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN); 197238104Sdes j > 0; 198238104Sdes j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) { 199238104Sdes if (cnt == 0) { 200238104Sdes /* the address */ 201238104Sdes if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 202238104Sdes word))) { 203238104Sdes /* ip6 */ 204238104Sdes ldns_rdf_deep_free(tmp); 205238104Sdes ip6 = true; 206238104Sdes } else { 207238104Sdes if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 208238104Sdes word))) { 209238104Sdes /* ip4 */ 210238104Sdes ldns_rdf_deep_free(tmp); 211238104Sdes ip6 = false; 212238104Sdes } else { 213238104Sdes /* kaput */ 214238104Sdes break; 215238104Sdes } 216238104Sdes } 217238104Sdes (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1); 218238104Sdes } else { 219238104Sdes /* la al la la */ 220238104Sdes if (ip6) { 221238104Sdes snprintf(rr_str, LDNS_MAX_LINELEN, 222238104Sdes "%s IN AAAA %s", word, addr); 223238104Sdes } else { 224238104Sdes snprintf(rr_str, LDNS_MAX_LINELEN, 225238104Sdes "%s IN A %s", word, addr); 226238104Sdes } 227238104Sdes parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL); 228238104Sdes if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) { 229238104Sdes ldns_rr_list_push_rr(list, ldns_rr_clone(rr)); 230238104Sdes } 231238104Sdes ldns_rr_free(rr); 232238104Sdes } 233238104Sdes } 234238104Sdes ldns_buffer_free(linebuf); 235238104Sdes } 236238104Sdes LDNS_FREE(line); 237238104Sdes LDNS_FREE(word); 238238104Sdes LDNS_FREE(addr); 239238104Sdes LDNS_FREE(rr_str); 240238104Sdes return list; 241238104Sdes} 242238104Sdes 243238104Sdesldns_rr_list * 244238104Sdesldns_get_rr_list_hosts_frm_file(char *filename) 245238104Sdes{ 246238104Sdes ldns_rr_list *names; 247238104Sdes FILE *fp; 248238104Sdes 249238104Sdes if (!filename) { 250238104Sdes fp = fopen(LDNS_RESOLV_HOSTS, "r"); 251238104Sdes 252238104Sdes } else { 253238104Sdes fp = fopen(filename, "r"); 254238104Sdes } 255238104Sdes if (!fp) { 256238104Sdes return NULL; 257238104Sdes } 258238104Sdes 259238104Sdes names = ldns_get_rr_list_hosts_frm_fp(fp); 260238104Sdes fclose(fp); 261238104Sdes return names; 262238104Sdes} 263238104Sdes 264238104Sdesuint16_t 265238104Sdesldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 266238104Sdes ldns_rr_list **ret) 267238104Sdes{ 268238104Sdes ldns_rdf_type t; 269238104Sdes uint16_t names_found; 270238104Sdes ldns_resolver *r; 271238104Sdes ldns_status s; 272238104Sdes 273238104Sdes t = ldns_rdf_get_type(node); 274238104Sdes names_found = 0; 275238104Sdes r = res; 276238104Sdes 277238104Sdes if (res == NULL) { 278238104Sdes /* prepare a new resolver, using /etc/resolv.conf as a guide */ 279238104Sdes s = ldns_resolver_new_frm_file(&r, NULL); 280238104Sdes if (s != LDNS_STATUS_OK) { 281238104Sdes return 0; 282238104Sdes } 283238104Sdes } 284238104Sdes 285238104Sdes if (t == LDNS_RDF_TYPE_DNAME) { 286238104Sdes /* we're asked to query for a name */ 287238104Sdes *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0); 288238104Sdes names_found = ldns_rr_list_rr_count(*ret); 289238104Sdes } 290238104Sdes 291238104Sdes if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) { 292238104Sdes /* an address */ 293238104Sdes *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0); 294238104Sdes names_found = ldns_rr_list_rr_count(*ret); 295238104Sdes } 296238104Sdes 297238104Sdes if (res == NULL) { 298238104Sdes ldns_resolver_deep_free(r); 299238104Sdes } 300238104Sdes 301238104Sdes return names_found; 302238104Sdes} 303238104Sdes 304238104Sdesbool 305238104Sdesldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t) 306238104Sdes{ 307269257Sdes switch (ldns_rr_get_type(nsec)) { 308269257Sdes case LDNS_RR_TYPE_NSEC : if (ldns_rr_rd_count(nsec) < 2) { 309269257Sdes return false; 310269257Sdes } 311269257Sdes return ldns_nsec_bitmap_covers_type( 312269257Sdes ldns_rr_rdf(nsec, 1), t); 313238104Sdes 314269257Sdes case LDNS_RR_TYPE_NSEC3 : if (ldns_rr_rd_count(nsec) < 6) { 315269257Sdes return false; 316269257Sdes } 317269257Sdes return ldns_nsec_bitmap_covers_type( 318269257Sdes ldns_rr_rdf(nsec, 5), t); 319238104Sdes 320269257Sdes default : return false; 321238104Sdes } 322238104Sdes} 323238104Sdes 324238104Sdesvoid 325238104Sdesldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...) 326238104Sdes{ 327238104Sdes int16_t rdf; 328238104Sdes ldns_rdf *rd; 329238104Sdes va_list va_rdf; 330238104Sdes va_start(va_rdf, rdfnum); 331238104Sdes 332238104Sdes for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 333238104Sdes { 334238104Sdes rd = ldns_rr_rdf(r, rdf); 335238104Sdes if (!rd) { 336238104Sdes continue; 337238104Sdes } else { 338238104Sdes ldns_rdf_print(fp, rd); 339238104Sdes fprintf(fp, " "); /* not sure if we want to do this */ 340238104Sdes } 341238104Sdes } 342238104Sdes va_end(va_rdf); 343238104Sdes} 344269257Sdes 345