1825eb42bSJan Lentfer /* 2825eb42bSJan Lentfer * higher.c 3825eb42bSJan Lentfer * 4825eb42bSJan Lentfer * Specify some higher level functions that would 5825eb42bSJan Lentfer * be usefull to would be developers 6825eb42bSJan Lentfer * 7825eb42bSJan Lentfer * a Net::DNS like library for C 8825eb42bSJan Lentfer * 9825eb42bSJan Lentfer * (c) NLnet Labs, 2004-2006 10825eb42bSJan Lentfer * 11825eb42bSJan Lentfer * See the file LICENSE for the license 12825eb42bSJan Lentfer */ 13825eb42bSJan Lentfer 14825eb42bSJan Lentfer #include <ldns/config.h> 15825eb42bSJan Lentfer 16825eb42bSJan Lentfer #include <ldns/ldns.h> 17825eb42bSJan Lentfer 18825eb42bSJan Lentfer #ifdef HAVE_SSL 19825eb42bSJan Lentfer #include <openssl/ssl.h> 20825eb42bSJan Lentfer #include <openssl/sha.h> 21825eb42bSJan Lentfer #endif /* HAVE_SSL */ 22825eb42bSJan Lentfer 23825eb42bSJan Lentfer ldns_rr_list * 24825eb42bSJan Lentfer ldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c, 25825eb42bSJan Lentfer uint16_t flags) 26825eb42bSJan Lentfer { 27825eb42bSJan Lentfer ldns_pkt *pkt; 28825eb42bSJan Lentfer ldns_rr_list *aaaa; 29825eb42bSJan Lentfer ldns_rr_list *a; 30825eb42bSJan Lentfer ldns_rr_list *result = NULL; 31825eb42bSJan Lentfer ldns_rr_list *hostsfilenames; 32825eb42bSJan Lentfer size_t i; 33825eb42bSJan Lentfer uint8_t ip6; 34825eb42bSJan Lentfer 35825eb42bSJan Lentfer a = NULL; 36825eb42bSJan Lentfer aaaa = NULL; 37825eb42bSJan Lentfer result = NULL; 38825eb42bSJan Lentfer 39825eb42bSJan Lentfer if (!res) { 40825eb42bSJan Lentfer return NULL; 41825eb42bSJan Lentfer } 42825eb42bSJan Lentfer if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { 43825eb42bSJan Lentfer return NULL; 44825eb42bSJan Lentfer } 45825eb42bSJan Lentfer 46825eb42bSJan Lentfer ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save 47825eb42bSJan Lentfer what was there */ 48825eb42bSJan Lentfer 49825eb42bSJan Lentfer ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY); 50825eb42bSJan Lentfer 51825eb42bSJan Lentfer hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL); 52825eb42bSJan Lentfer for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) { 53825eb42bSJan Lentfer if (ldns_rdf_compare(name, 54825eb42bSJan Lentfer ldns_rr_owner(ldns_rr_list_rr(hostsfilenames, 55825eb42bSJan Lentfer i))) == 0) { 56825eb42bSJan Lentfer if (!result) { 57825eb42bSJan Lentfer result = ldns_rr_list_new(); 58825eb42bSJan Lentfer } 59825eb42bSJan Lentfer ldns_rr_list_push_rr(result, 60825eb42bSJan Lentfer ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i))); 61825eb42bSJan Lentfer } 62825eb42bSJan Lentfer } 63825eb42bSJan Lentfer ldns_rr_list_deep_free(hostsfilenames); 64825eb42bSJan Lentfer 65825eb42bSJan Lentfer if (result) { 66825eb42bSJan Lentfer return result; 67825eb42bSJan Lentfer } 68825eb42bSJan Lentfer 69825eb42bSJan Lentfer /* add the RD flags, because we want an answer */ 70825eb42bSJan Lentfer pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD); 71825eb42bSJan Lentfer if (pkt) { 72825eb42bSJan Lentfer /* extract the data we need */ 73825eb42bSJan Lentfer aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA, 74825eb42bSJan Lentfer LDNS_SECTION_ANSWER); 75825eb42bSJan Lentfer ldns_pkt_free(pkt); 76825eb42bSJan Lentfer } 77825eb42bSJan Lentfer 78825eb42bSJan Lentfer pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD); 79825eb42bSJan Lentfer if (pkt) { 80825eb42bSJan Lentfer /* extract the data we need */ 81825eb42bSJan Lentfer a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER); 82825eb42bSJan Lentfer ldns_pkt_free(pkt); 83825eb42bSJan Lentfer } 84825eb42bSJan Lentfer ldns_resolver_set_ip6(res, ip6); 85825eb42bSJan Lentfer 86825eb42bSJan Lentfer if (aaaa && a) { 87825eb42bSJan Lentfer result = ldns_rr_list_cat_clone(aaaa, a); 88825eb42bSJan Lentfer ldns_rr_list_deep_free(aaaa); 89825eb42bSJan Lentfer ldns_rr_list_deep_free(a); 90825eb42bSJan Lentfer return result; 91825eb42bSJan Lentfer } 92825eb42bSJan Lentfer 93825eb42bSJan Lentfer if (aaaa) { 94825eb42bSJan Lentfer result = ldns_rr_list_clone(aaaa); 95825eb42bSJan Lentfer } 96825eb42bSJan Lentfer 97825eb42bSJan Lentfer if (a) { 98825eb42bSJan Lentfer result = ldns_rr_list_clone(a); 99825eb42bSJan Lentfer } 100825eb42bSJan Lentfer 101825eb42bSJan Lentfer ldns_rr_list_deep_free(aaaa); 102825eb42bSJan Lentfer ldns_rr_list_deep_free(a); 103825eb42bSJan Lentfer return result; 104825eb42bSJan Lentfer } 105825eb42bSJan Lentfer 106825eb42bSJan Lentfer ldns_rr_list * 107825eb42bSJan Lentfer ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c, 108825eb42bSJan Lentfer uint16_t flags) 109825eb42bSJan Lentfer { 110825eb42bSJan Lentfer ldns_pkt *pkt; 111825eb42bSJan Lentfer ldns_rr_list *names; 112825eb42bSJan Lentfer ldns_rdf *name; 113825eb42bSJan Lentfer 114825eb42bSJan Lentfer names = NULL; 115825eb42bSJan Lentfer 116825eb42bSJan Lentfer if (!res || !addr) { 117825eb42bSJan Lentfer return NULL; 118825eb42bSJan Lentfer } 119825eb42bSJan Lentfer 120825eb42bSJan Lentfer if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A && 121825eb42bSJan Lentfer ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) { 122825eb42bSJan Lentfer return NULL; 123825eb42bSJan Lentfer } 124825eb42bSJan Lentfer 125825eb42bSJan Lentfer name = ldns_rdf_address_reverse(addr); 126825eb42bSJan Lentfer 127825eb42bSJan Lentfer /* add the RD flags, because we want an answer */ 128825eb42bSJan Lentfer pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD); 129*d1b2b5caSJohn Marino ldns_rdf_deep_free(name); 130825eb42bSJan Lentfer if (pkt) { 131825eb42bSJan Lentfer /* extract the data we need */ 132825eb42bSJan Lentfer names = ldns_pkt_rr_list_by_type(pkt, 133825eb42bSJan Lentfer LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER); 134825eb42bSJan Lentfer } 135825eb42bSJan Lentfer return names; 136825eb42bSJan Lentfer } 137825eb42bSJan Lentfer 138825eb42bSJan Lentfer /* read a line, put it in a buffer, parse the buffer */ 139825eb42bSJan Lentfer ldns_rr_list * 140825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_fp(FILE *fp) 141825eb42bSJan Lentfer { 142825eb42bSJan Lentfer return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL); 143825eb42bSJan Lentfer } 144825eb42bSJan Lentfer 145825eb42bSJan Lentfer ldns_rr_list * 146825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) 147825eb42bSJan Lentfer { 148825eb42bSJan Lentfer ssize_t i, j; 149825eb42bSJan Lentfer size_t cnt; 150825eb42bSJan Lentfer char *line; 151825eb42bSJan Lentfer char *word; 152825eb42bSJan Lentfer char *addr; 153825eb42bSJan Lentfer char *rr_str; 154825eb42bSJan Lentfer ldns_buffer *linebuf; 155825eb42bSJan Lentfer ldns_rr *rr; 156825eb42bSJan Lentfer ldns_rr_list *list; 157825eb42bSJan Lentfer ldns_rdf *tmp; 158825eb42bSJan Lentfer bool ip6; 159825eb42bSJan Lentfer ldns_status parse_result; 160825eb42bSJan Lentfer 161825eb42bSJan Lentfer line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 162825eb42bSJan Lentfer word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 163825eb42bSJan Lentfer addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 164825eb42bSJan Lentfer rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); 165825eb42bSJan Lentfer ip6 = false; 166825eb42bSJan Lentfer list = ldns_rr_list_new(); 167825eb42bSJan Lentfer rr = NULL; 168ac996e71SJan Lentfer if(!line || !word || !addr || !rr_str || !list) { 169ac996e71SJan Lentfer LDNS_FREE(line); 170ac996e71SJan Lentfer LDNS_FREE(word); 171ac996e71SJan Lentfer LDNS_FREE(addr); 172ac996e71SJan Lentfer LDNS_FREE(rr_str); 173ac996e71SJan Lentfer ldns_rr_list_free(list); 174ac996e71SJan Lentfer return NULL; 175ac996e71SJan Lentfer } 176825eb42bSJan Lentfer 177fd185f4dSJan Lentfer for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr); 178fd185f4dSJan Lentfer i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) { 179825eb42bSJan Lentfer /* # is comment */ 180825eb42bSJan Lentfer if (line[0] == '#') { 181825eb42bSJan Lentfer continue; 182825eb42bSJan Lentfer } 183825eb42bSJan Lentfer /* put it in a buffer for further processing */ 184825eb42bSJan Lentfer linebuf = LDNS_MALLOC(ldns_buffer); 185ac996e71SJan Lentfer if(!linebuf) { 186ac996e71SJan Lentfer LDNS_FREE(line); 187ac996e71SJan Lentfer LDNS_FREE(word); 188ac996e71SJan Lentfer LDNS_FREE(addr); 189ac996e71SJan Lentfer LDNS_FREE(rr_str); 190ac996e71SJan Lentfer ldns_rr_list_deep_free(list); 191ac996e71SJan Lentfer return NULL; 192ac996e71SJan Lentfer } 193825eb42bSJan Lentfer 194825eb42bSJan Lentfer ldns_buffer_new_frm_data(linebuf, line, (size_t) i); 195fd185f4dSJan Lentfer for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN); 196825eb42bSJan Lentfer j > 0; 197fd185f4dSJan Lentfer j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) { 198825eb42bSJan Lentfer if (cnt == 0) { 199825eb42bSJan Lentfer /* the address */ 200825eb42bSJan Lentfer if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 201825eb42bSJan Lentfer word))) { 202825eb42bSJan Lentfer /* ip6 */ 203825eb42bSJan Lentfer ldns_rdf_deep_free(tmp); 204825eb42bSJan Lentfer ip6 = true; 205825eb42bSJan Lentfer } else { 206825eb42bSJan Lentfer if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 207825eb42bSJan Lentfer word))) { 208825eb42bSJan Lentfer /* ip4 */ 209825eb42bSJan Lentfer ldns_rdf_deep_free(tmp); 210825eb42bSJan Lentfer ip6 = false; 211825eb42bSJan Lentfer } else { 212825eb42bSJan Lentfer /* kaput */ 213825eb42bSJan Lentfer break; 214825eb42bSJan Lentfer } 215825eb42bSJan Lentfer } 216fd185f4dSJan Lentfer (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1); 217825eb42bSJan Lentfer } else { 218825eb42bSJan Lentfer /* la al la la */ 219825eb42bSJan Lentfer if (ip6) { 220825eb42bSJan Lentfer snprintf(rr_str, LDNS_MAX_LINELEN, 221825eb42bSJan Lentfer "%s IN AAAA %s", word, addr); 222825eb42bSJan Lentfer } else { 223825eb42bSJan Lentfer snprintf(rr_str, LDNS_MAX_LINELEN, 224825eb42bSJan Lentfer "%s IN A %s", word, addr); 225825eb42bSJan Lentfer } 226825eb42bSJan Lentfer parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL); 227825eb42bSJan Lentfer if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) { 228825eb42bSJan Lentfer ldns_rr_list_push_rr(list, ldns_rr_clone(rr)); 229825eb42bSJan Lentfer } 230825eb42bSJan Lentfer ldns_rr_free(rr); 231825eb42bSJan Lentfer } 232825eb42bSJan Lentfer } 233825eb42bSJan Lentfer ldns_buffer_free(linebuf); 234825eb42bSJan Lentfer } 235825eb42bSJan Lentfer LDNS_FREE(line); 236825eb42bSJan Lentfer LDNS_FREE(word); 237825eb42bSJan Lentfer LDNS_FREE(addr); 238825eb42bSJan Lentfer LDNS_FREE(rr_str); 239825eb42bSJan Lentfer return list; 240825eb42bSJan Lentfer } 241825eb42bSJan Lentfer 242825eb42bSJan Lentfer ldns_rr_list * 243825eb42bSJan Lentfer ldns_get_rr_list_hosts_frm_file(char *filename) 244825eb42bSJan Lentfer { 245825eb42bSJan Lentfer ldns_rr_list *names; 246825eb42bSJan Lentfer FILE *fp; 247825eb42bSJan Lentfer 248825eb42bSJan Lentfer if (!filename) { 249825eb42bSJan Lentfer fp = fopen(LDNS_RESOLV_HOSTS, "r"); 250825eb42bSJan Lentfer 251825eb42bSJan Lentfer } else { 252825eb42bSJan Lentfer fp = fopen(filename, "r"); 253825eb42bSJan Lentfer } 254825eb42bSJan Lentfer if (!fp) { 255825eb42bSJan Lentfer return NULL; 256825eb42bSJan Lentfer } 257825eb42bSJan Lentfer 258825eb42bSJan Lentfer names = ldns_get_rr_list_hosts_frm_fp(fp); 259825eb42bSJan Lentfer fclose(fp); 260825eb42bSJan Lentfer return names; 261825eb42bSJan Lentfer } 262825eb42bSJan Lentfer 263825eb42bSJan Lentfer uint16_t 264825eb42bSJan Lentfer ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 265825eb42bSJan Lentfer ldns_rr_list **ret) 266825eb42bSJan Lentfer { 267825eb42bSJan Lentfer ldns_rdf_type t; 268825eb42bSJan Lentfer uint16_t names_found; 269825eb42bSJan Lentfer ldns_resolver *r; 270825eb42bSJan Lentfer ldns_status s; 271825eb42bSJan Lentfer 272825eb42bSJan Lentfer t = ldns_rdf_get_type(node); 273825eb42bSJan Lentfer names_found = 0; 274825eb42bSJan Lentfer r = res; 275825eb42bSJan Lentfer 276825eb42bSJan Lentfer if (res == NULL) { 277825eb42bSJan Lentfer /* prepare a new resolver, using /etc/resolv.conf as a guide */ 278825eb42bSJan Lentfer s = ldns_resolver_new_frm_file(&r, NULL); 279825eb42bSJan Lentfer if (s != LDNS_STATUS_OK) { 280825eb42bSJan Lentfer return 0; 281825eb42bSJan Lentfer } 282825eb42bSJan Lentfer } 283825eb42bSJan Lentfer 284825eb42bSJan Lentfer if (t == LDNS_RDF_TYPE_DNAME) { 285825eb42bSJan Lentfer /* we're asked to query for a name */ 286825eb42bSJan Lentfer *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0); 287825eb42bSJan Lentfer names_found = ldns_rr_list_rr_count(*ret); 288825eb42bSJan Lentfer } 289825eb42bSJan Lentfer 290825eb42bSJan Lentfer if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) { 291825eb42bSJan Lentfer /* an address */ 292825eb42bSJan Lentfer *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0); 293825eb42bSJan Lentfer names_found = ldns_rr_list_rr_count(*ret); 294825eb42bSJan Lentfer } 295825eb42bSJan Lentfer 296825eb42bSJan Lentfer if (res == NULL) { 297825eb42bSJan Lentfer ldns_resolver_deep_free(r); 298825eb42bSJan Lentfer } 299825eb42bSJan Lentfer 300825eb42bSJan Lentfer return names_found; 301825eb42bSJan Lentfer } 302825eb42bSJan Lentfer 303825eb42bSJan Lentfer bool 304825eb42bSJan Lentfer ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t) 305825eb42bSJan Lentfer { 306825eb42bSJan Lentfer /* does the nsec cover the t given? */ 307825eb42bSJan Lentfer /* copied from host2str.c line 465: ldns_rdf2buffer_str_nsec */ 308825eb42bSJan Lentfer uint8_t window_block_nr; 309825eb42bSJan Lentfer uint8_t bitmap_length; 310825eb42bSJan Lentfer uint16_t type; 311825eb42bSJan Lentfer uint16_t pos = 0; 312825eb42bSJan Lentfer uint16_t bit_pos; 313825eb42bSJan Lentfer ldns_rdf *nsec_type_list = ldns_rr_rdf(nsec, 1); 314b5dedccaSJan Lentfer uint8_t *data; 315b5dedccaSJan Lentfer 316b5dedccaSJan Lentfer if (nsec_type_list == NULL) { 317b5dedccaSJan Lentfer return false; 318b5dedccaSJan Lentfer } 319b5dedccaSJan Lentfer data = ldns_rdf_data(nsec_type_list); 320825eb42bSJan Lentfer 321825eb42bSJan Lentfer while(pos < ldns_rdf_size(nsec_type_list)) { 322825eb42bSJan Lentfer window_block_nr = data[pos]; 323825eb42bSJan Lentfer bitmap_length = data[pos + 1]; 324825eb42bSJan Lentfer pos += 2; 325825eb42bSJan Lentfer 326825eb42bSJan Lentfer for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) { 327825eb42bSJan Lentfer if (ldns_get_bit(&data[pos], bit_pos)) { 328825eb42bSJan Lentfer type = 256 * (uint16_t) window_block_nr + bit_pos; 329825eb42bSJan Lentfer 330825eb42bSJan Lentfer if ((ldns_rr_type)type == t) { 331825eb42bSJan Lentfer /* we have a winner */ 332825eb42bSJan Lentfer return true; 333825eb42bSJan Lentfer } 334825eb42bSJan Lentfer } 335825eb42bSJan Lentfer } 336825eb42bSJan Lentfer pos += (uint16_t) bitmap_length; 337825eb42bSJan Lentfer } 338825eb42bSJan Lentfer return false; 339825eb42bSJan Lentfer } 340825eb42bSJan Lentfer 341825eb42bSJan Lentfer void 342825eb42bSJan Lentfer ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...) 343825eb42bSJan Lentfer { 344825eb42bSJan Lentfer int16_t rdf; 345825eb42bSJan Lentfer ldns_rdf *rd; 346825eb42bSJan Lentfer va_list va_rdf; 347825eb42bSJan Lentfer va_start(va_rdf, rdfnum); 348825eb42bSJan Lentfer 349825eb42bSJan Lentfer for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 350825eb42bSJan Lentfer { 351825eb42bSJan Lentfer rd = ldns_rr_rdf(r, rdf); 352825eb42bSJan Lentfer if (!rd) { 353825eb42bSJan Lentfer continue; 354825eb42bSJan Lentfer } else { 355825eb42bSJan Lentfer ldns_rdf_print(fp, rd); 356825eb42bSJan Lentfer fprintf(fp, " "); /* not sure if we want to do this */ 357825eb42bSJan Lentfer } 358825eb42bSJan Lentfer } 359825eb42bSJan Lentfer va_end(va_rdf); 360825eb42bSJan Lentfer } 361