higher.c revision 269257
1117395Skan/* 2169689Skan * higher.c 3169689Skan * 4117395Skan * Specify some higher level functions that would 5117395Skan * be usefull to would be developers 6117395Skan * 7132718Skan * a Net::DNS like library for C 8132718Skan * 9132718Skan * (c) NLnet Labs, 2004-2006 10117395Skan * 11117395Skan * See the file LICENSE for the license 12117395Skan */ 13117395Skan 14132718Skan#include <ldns/config.h> 15117395Skan 16117395Skan#include <ldns/ldns.h> 17117395Skan 18117395Skan#ifdef HAVE_SSL 19117395Skan#include <openssl/ssl.h> 20132718Skan#include <openssl/sha.h> 21169689Skan#endif /* HAVE_SSL */ 22169689Skan 23117395Skanldns_rr_list * 24117395Skanldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c, 25132718Skan uint16_t flags) 26117395Skan{ 27117395Skan ldns_pkt *pkt; 28117395Skan ldns_rr_list *aaaa; 29117395Skan ldns_rr_list *a; 30117395Skan ldns_rr_list *result = NULL; 31117395Skan ldns_rr_list *hostsfilenames; 32117395Skan size_t i; 33117395Skan uint8_t ip6; 34117395Skan 35117395Skan a = NULL; 36117395Skan aaaa = NULL; 37117395Skan result = NULL; 38117395Skan 39117395Skan if (!res) { 40117395Skan return NULL; 41117395Skan } 42117395Skan if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { 43132718Skan return NULL; 44132718Skan } 45117395Skan 46117395Skan ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save 47117395Skan what was there */ 48117395Skan 49117395Skan ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY); 50117395Skan 51117395Skan hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL); 52132718Skan for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) { 53132718Skan if (ldns_rdf_compare(name, 54117395Skan ldns_rr_owner(ldns_rr_list_rr(hostsfilenames, 55117395Skan i))) == 0) { 56117395Skan if (!result) { 57117395Skan result = ldns_rr_list_new(); 58117395Skan } 59117395Skan ldns_rr_list_push_rr(result, 60117395Skan ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i))); 61117395Skan } 62132718Skan } 63117395Skan ldns_rr_list_deep_free(hostsfilenames); 64117395Skan 65117395Skan if (result) { 66117395Skan return result; 67117395Skan } 68117395Skan 69117395Skan /* add the RD flags, because we want an answer */ 70117395Skan pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD); 71132718Skan if (pkt) { 72132718Skan /* extract the data we need */ 73117395Skan aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA, 74117395Skan LDNS_SECTION_ANSWER); 75117395Skan ldns_pkt_free(pkt); 76117395Skan } 77132718Skan 78117395Skan pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD); 79117395Skan if (pkt) { 80117395Skan /* extract the data we need */ 81117395Skan a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER); 82117395Skan ldns_pkt_free(pkt); 83117395Skan } 84117395Skan ldns_resolver_set_ip6(res, ip6); 85117395Skan 86117395Skan if (aaaa && a) { 87117395Skan result = ldns_rr_list_cat_clone(aaaa, a); 88117395Skan ldns_rr_list_deep_free(aaaa); 89117395Skan ldns_rr_list_deep_free(a); 90132718Skan return result; 91117395Skan } 92117395Skan 93117395Skan if (aaaa) { 94117395Skan result = ldns_rr_list_clone(aaaa); 95117395Skan } 96117395Skan 97117395Skan if (a) { 98117395Skan result = ldns_rr_list_clone(a); 99117395Skan } 100117395Skan 101117395Skan ldns_rr_list_deep_free(aaaa); 102117395Skan ldns_rr_list_deep_free(a); 103117395Skan return result; 104117395Skan} 105132718Skan 106117395Skanldns_rr_list * 107132718Skanldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c, 108132718Skan uint16_t flags) 109117395Skan{ 110117395Skan ldns_pkt *pkt; 111117395Skan ldns_rr_list *names; 112169689Skan ldns_rdf *name; 113117395Skan 114117395Skan names = NULL; 115117395Skan 116169689Skan if (!res || !addr) { 117117395Skan return NULL; 118117395Skan } 119117395Skan 120117395Skan if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A && 121117395Skan ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) { 122117395Skan return NULL; 123117395Skan } 124117395Skan 125117395Skan name = ldns_rdf_address_reverse(addr); 126117395Skan 127117395Skan /* add the RD flags, because we want an answer */ 128117395Skan pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD); 129117395Skan ldns_rdf_deep_free(name); 130117395Skan if (pkt) { 131117395Skan /* extract the data we need */ 132117395Skan names = ldns_pkt_rr_list_by_type(pkt, 133117395Skan LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER); 134117395Skan ldns_pkt_free(pkt); 135117395Skan } 136117395Skan return names; 137117395Skan} 138117395Skan 139117395Skan/* read a line, put it in a buffer, parse the buffer */ 140117395Skanldns_rr_list * 141117395Skanldns_get_rr_list_hosts_frm_fp(FILE *fp) 142117395Skan{ 143117395Skan return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL); 144117395Skan} 145117395Skan 146117395Skanldns_rr_list * 147117395Skanldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) 148117395Skan{ 149117395Skan ssize_t i, j; 150117395Skan size_t cnt; 151117395Skan char *line; 152117395Skan char *word; 153117395Skan char *addr; 154117395Skan char *rr_str; 155117395Skan ldns_buffer *linebuf; 156117395Skan ldns_rr *rr; 157117395Skan ldns_rr_list *list; 158117395Skan ldns_rdf *tmp; 159132718Skan bool ip6; 160117395Skan ldns_status parse_result; 161117395Skan 162117395Skan line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 163117395Skan word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 164117395Skan addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 165117395Skan rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 166117395Skan ip6 = false; 167117395Skan list = ldns_rr_list_new(); 168117395Skan rr = NULL; 169117395Skan if(!line || !word || !addr || !rr_str || !list) { 170117395Skan LDNS_FREE(line); 171117395Skan LDNS_FREE(word); 172117395Skan LDNS_FREE(addr); 173117395Skan LDNS_FREE(rr_str); 174132718Skan ldns_rr_list_free(list); 175132718Skan return NULL; 176117395Skan } 177117395Skan 178117395Skan for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr); 179117395Skan i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) { 180117395Skan /* # is comment */ 181117395Skan if (line[0] == '#') { 182117395Skan continue; 183117395Skan } 184117395Skan /* put it in a buffer for further processing */ 185117395Skan linebuf = LDNS_MALLOC(ldns_buffer); 186117395Skan if(!linebuf) { 187117395Skan LDNS_FREE(line); 188132718Skan LDNS_FREE(word); 189132718Skan LDNS_FREE(addr); 190117395Skan LDNS_FREE(rr_str); 191117395Skan ldns_rr_list_deep_free(list); 192117395Skan return NULL; 193117395Skan } 194117395Skan 195117395Skan ldns_buffer_new_frm_data(linebuf, line, (size_t) i); 196117395Skan for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN); 197117395Skan j > 0; 198117395Skan j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) { 199117395Skan if (cnt == 0) { 200117395Skan /* the address */ 201117395Skan if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 202117395Skan word))) { 203117395Skan /* ip6 */ 204117395Skan ldns_rdf_deep_free(tmp); 205169689Skan ip6 = true; 206117395Skan } else { 207169689Skan if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 208169689Skan word))) { 209169689Skan /* ip4 */ 210169689Skan ldns_rdf_deep_free(tmp); 211169689Skan ip6 = false; 212169689Skan } else { 213169689Skan /* kaput */ 214169689Skan break; 215169689Skan } 216169689Skan } 217117395Skan (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1); 218169689Skan } else { 219169689Skan /* la al la la */ 220169689Skan if (ip6) { 221169689Skan snprintf(rr_str, LDNS_MAX_LINELEN, 222169689Skan "%s IN AAAA %s", word, addr); 223169689Skan } else { 224169689Skan snprintf(rr_str, LDNS_MAX_LINELEN, 225169689Skan "%s IN A %s", word, addr); 226169689Skan } 227169689Skan parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL); 228169689Skan if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) { 229169689Skan ldns_rr_list_push_rr(list, ldns_rr_clone(rr)); 230169689Skan } 231169689Skan ldns_rr_free(rr); 232169689Skan } 233117395Skan } 234117395Skan ldns_buffer_free(linebuf); 235117395Skan } 236117395Skan LDNS_FREE(line); 237117395Skan LDNS_FREE(word); 238117395Skan LDNS_FREE(addr); 239117395Skan LDNS_FREE(rr_str); 240117395Skan return list; 241117395Skan} 242117395Skan 243117395Skanldns_rr_list * 244117395Skanldns_get_rr_list_hosts_frm_file(char *filename) 245117395Skan{ 246117395Skan ldns_rr_list *names; 247117395Skan FILE *fp; 248117395Skan 249117395Skan if (!filename) { 250132718Skan fp = fopen(LDNS_RESOLV_HOSTS, "r"); 251132718Skan 252117395Skan } else { 253117395Skan fp = fopen(filename, "r"); 254117395Skan } 255117395Skan if (!fp) { 256117395Skan return NULL; 257117395Skan } 258117395Skan 259117395Skan names = ldns_get_rr_list_hosts_frm_fp(fp); 260117395Skan fclose(fp); 261117395Skan return names; 262117395Skan} 263117395Skan 264117395Skanuint16_t 265117395Skanldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 266117395Skan ldns_rr_list **ret) 267117395Skan{ 268117395Skan ldns_rdf_type t; 269117395Skan uint16_t names_found; 270117395Skan ldns_resolver *r; 271117395Skan ldns_status s; 272117395Skan 273117395Skan t = ldns_rdf_get_type(node); 274132718Skan names_found = 0; 275132718Skan r = res; 276132718Skan 277132718Skan if (res == NULL) { 278117395Skan /* prepare a new resolver, using /etc/resolv.conf as a guide */ 279117395Skan s = ldns_resolver_new_frm_file(&r, NULL); 280117395Skan if (s != LDNS_STATUS_OK) { 281117395Skan return 0; 282117395Skan } 283117395Skan } 284117395Skan 285117395Skan if (t == LDNS_RDF_TYPE_DNAME) { 286117395Skan /* we're asked to query for a name */ 287117395Skan *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0); 288117395Skan names_found = ldns_rr_list_rr_count(*ret); 289117395Skan } 290117395Skan 291117395Skan if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) { 292117395Skan /* an address */ 293117395Skan *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0); 294117395Skan names_found = ldns_rr_list_rr_count(*ret); 295117395Skan } 296117395Skan 297117395Skan if (res == NULL) { 298117395Skan ldns_resolver_deep_free(r); 299117395Skan } 300117395Skan 301117395Skan return names_found; 302117395Skan} 303117395Skan 304117395Skanbool 305117395Skanldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t) 306117395Skan{ 307117395Skan switch (ldns_rr_get_type(nsec)) { 308117395Skan case LDNS_RR_TYPE_NSEC : if (ldns_rr_rd_count(nsec) < 2) { 309117395Skan return false; 310117395Skan } 311117395Skan return ldns_nsec_bitmap_covers_type( 312117395Skan ldns_rr_rdf(nsec, 1), t); 313117395Skan 314117395Skan case LDNS_RR_TYPE_NSEC3 : if (ldns_rr_rd_count(nsec) < 6) { 315117395Skan return false; 316117395Skan } 317117395Skan return ldns_nsec_bitmap_covers_type( 318169689Skan ldns_rr_rdf(nsec, 5), t); 319117395Skan 320169689Skan default : return false; 321117395Skan } 322117395Skan} 323117395Skan 324117395Skanvoid 325117395Skanldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...) 326117395Skan{ 327117395Skan int16_t rdf; 328117395Skan ldns_rdf *rd; 329117395Skan va_list va_rdf; 330117395Skan va_start(va_rdf, rdfnum); 331117395Skan 332117395Skan for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 333117395Skan { 334117395Skan rd = ldns_rr_rdf(r, rdf); 335117395Skan if (!rd) { 336117395Skan continue; 337117395Skan } else { 338117395Skan ldns_rdf_print(fp, rd); 339117395Skan fprintf(fp, " "); /* not sure if we want to do this */ 340117395Skan } 341117395Skan } 342132718Skan va_end(va_rdf); 343132718Skan} 344132718Skan 345132718Skan