higher.c
Go to the documentation of this file.
00001 /*
00002  * higher.c
00003  *
00004  * Specify some higher level functions that would
00005  * be usefull to would be developers
00006  *
00007  * a Net::DNS like library for C
00008  *
00009  * (c) NLnet Labs, 2004-2006
00010  *
00011  * See the file LICENSE for the license
00012  */
00013 
00014 #include <ldns/config.h>
00015 
00016 #include <ldns/ldns.h>
00017 
00018 #ifdef HAVE_SSL
00019 #include <openssl/ssl.h>
00020 #include <openssl/sha.h>
00021 #endif /* HAVE_SSL */
00022 
00023 ldns_rr_list *
00024 ldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c, 
00025                 uint16_t flags)
00026 {
00027         ldns_pkt *pkt;
00028         ldns_rr_list *aaaa;
00029         ldns_rr_list *a;
00030         ldns_rr_list *result = NULL;
00031         ldns_rr_list *hostsfilenames;
00032         size_t i;
00033         uint8_t ip6;
00034 
00035         a = NULL; 
00036         aaaa = NULL; 
00037         result = NULL;
00038 
00039         if (!res) {
00040                 return NULL;
00041         }
00042         if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
00043                 return NULL;
00044         }
00045 
00046         ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save
00047                                          what was there */
00048 
00049         ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY);
00050         
00051         hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL);
00052         for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) {
00053                 if (ldns_rdf_compare(name, 
00054                                         ldns_rr_owner(ldns_rr_list_rr(hostsfilenames, 
00055                                                         i))) == 0) {
00056                         if (!result) {
00057                                 result = ldns_rr_list_new();
00058                         }
00059                         ldns_rr_list_push_rr(result, 
00060                                         ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i)));
00061                 }
00062         }
00063         ldns_rr_list_deep_free(hostsfilenames);
00064 
00065         if (result) {
00066                 return result;
00067         }
00068 
00069         /* add the RD flags, because we want an answer */
00070         pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD);
00071         if (pkt) {
00072                 /* extract the data we need */
00073                 aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA, 
00074                         LDNS_SECTION_ANSWER);
00075                 ldns_pkt_free(pkt);
00076         } 
00077 
00078         pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD);
00079         if (pkt) {
00080                 /* extract the data we need */
00081                 a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER);
00082                 ldns_pkt_free(pkt);
00083         } 
00084         ldns_resolver_set_ip6(res, ip6);
00085 
00086         if (aaaa && a) {
00087                 result = ldns_rr_list_cat_clone(aaaa, a);
00088                 ldns_rr_list_deep_free(aaaa);
00089                 ldns_rr_list_deep_free(a);
00090                 return result;
00091         }
00092         
00093         if (aaaa) {
00094                 result = ldns_rr_list_clone(aaaa);
00095         }
00096         
00097         if (a) {
00098                 result = ldns_rr_list_clone(a);
00099         }
00100 
00101         ldns_rr_list_deep_free(aaaa);
00102         ldns_rr_list_deep_free(a);
00103         return result;
00104 }
00105 
00106 ldns_rr_list *
00107 ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c, 
00108                 uint16_t flags)
00109 {
00110         ldns_pkt *pkt;
00111         ldns_rr_list *names;
00112         ldns_rdf *name;
00113 
00114         names = NULL;
00115 
00116         if (!res || !addr) {
00117                 return NULL;
00118         }
00119 
00120         if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A &&
00121                         ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) {
00122                 return NULL;
00123         }
00124 
00125         name = ldns_rdf_address_reverse(addr);
00126         
00127         /* add the RD flags, because we want an answer */
00128         pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD);
00129         ldns_rdf_deep_free(name);
00130         if (pkt) {
00131                 /* extract the data we need */
00132                 names = ldns_pkt_rr_list_by_type(pkt, 
00133                                 LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER);
00134                 ldns_pkt_free(pkt);
00135         }
00136         return names;
00137 }
00138 
00139 /* read a line, put it in a buffer, parse the buffer */
00140 ldns_rr_list *
00141 ldns_get_rr_list_hosts_frm_fp(FILE *fp)
00142 {
00143         return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
00144 }
00145 
00146 ldns_rr_list *
00147 ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
00148 {
00149         ssize_t i, j;
00150         size_t cnt;
00151         char *line;
00152         char *word;
00153         char *addr;
00154         char *rr_str;
00155         ldns_buffer *linebuf;
00156         ldns_rr *rr;
00157         ldns_rr_list *list;
00158         ldns_rdf *tmp;
00159         bool ip6;
00160         ldns_status parse_result;
00161 
00162         line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00163         word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00164         addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00165         rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00166         ip6 = false;
00167         list = ldns_rr_list_new();
00168         rr = NULL;
00169         if(!line || !word || !addr || !rr_str || !list) {
00170                 LDNS_FREE(line);
00171                 LDNS_FREE(word);
00172                 LDNS_FREE(addr);
00173                 LDNS_FREE(rr_str);
00174                 ldns_rr_list_free(list);
00175                 return NULL;
00176         }
00177 
00178         for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
00179                         i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
00180                 /* # is comment */
00181                 if (line[0] == '#') {
00182                         continue;
00183                 }
00184                 /* put it in a buffer for further processing */
00185                 linebuf = LDNS_MALLOC(ldns_buffer);
00186                 if(!linebuf) {
00187                         LDNS_FREE(line);
00188                         LDNS_FREE(word);
00189                         LDNS_FREE(addr);
00190                         LDNS_FREE(rr_str);
00191                         ldns_rr_list_deep_free(list);
00192                         return NULL;
00193                 }
00194 
00195                 ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
00196                 for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
00197                                 j > 0;
00198                                 j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
00199                         if (cnt == 0) {
00200                                 /* the address */
00201                                 if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 
00202                                                                 word))) {
00203                                         /* ip6 */
00204                                         ldns_rdf_deep_free(tmp);
00205                                         ip6 = true;
00206                                 } else {
00207                                         if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 
00208                                                                         word))) {
00209                                                 /* ip4 */
00210                                                 ldns_rdf_deep_free(tmp);
00211                                                 ip6 = false;
00212                                         } else {
00213                                                 /* kaput */
00214                                                 break;
00215                                         }
00216                                 }
00217                                 (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
00218                         } else {
00219                                 /* la al la la */
00220                                 if (ip6) {
00221                                         snprintf(rr_str, LDNS_MAX_LINELEN, 
00222                                                 "%s IN AAAA %s", word, addr);
00223                                 } else {
00224                                         snprintf(rr_str, LDNS_MAX_LINELEN, 
00225                                                 "%s IN A %s", word, addr);
00226                                 }
00227                                 parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
00228                                 if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
00229                                         ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
00230                                 }
00231                                 ldns_rr_free(rr);
00232                         }
00233                 }
00234                 ldns_buffer_free(linebuf);
00235         }
00236         LDNS_FREE(line);
00237         LDNS_FREE(word);
00238         LDNS_FREE(addr);
00239         LDNS_FREE(rr_str);
00240         return list;
00241 }
00242 
00243 ldns_rr_list *
00244 ldns_get_rr_list_hosts_frm_file(char *filename)
00245 {
00246         ldns_rr_list *names;
00247         FILE *fp;
00248 
00249         if (!filename) {
00250                 fp = fopen(LDNS_RESOLV_HOSTS, "r");
00251         
00252         } else {
00253                 fp = fopen(filename, "r");
00254         }
00255         if (!fp) {
00256                 return NULL;
00257         }
00258 
00259         names = ldns_get_rr_list_hosts_frm_fp(fp);
00260         fclose(fp);
00261         return names;
00262 }
00263 
00264 uint16_t
00265 ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 
00266                 ldns_rr_list **ret)
00267 {
00268         ldns_rdf_type t;
00269         uint16_t names_found;
00270         ldns_resolver *r;
00271         ldns_status s;
00272 
00273         t = ldns_rdf_get_type(node);
00274         names_found = 0;
00275         r = res;
00276 
00277         if (res == NULL) {
00278                 /* prepare a new resolver, using /etc/resolv.conf as a guide  */
00279                 s = ldns_resolver_new_frm_file(&r, NULL);
00280                 if (s != LDNS_STATUS_OK) {
00281                         return 0;
00282                 } 
00283         }
00284 
00285         if (t == LDNS_RDF_TYPE_DNAME) {
00286                 /* we're asked to query for a name */
00287                 *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
00288                 names_found = ldns_rr_list_rr_count(*ret);
00289         }
00290 
00291         if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
00292                 /* an address */
00293                 *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
00294                 names_found = ldns_rr_list_rr_count(*ret);
00295         }
00296 
00297         if (res == NULL) {
00298                 ldns_resolver_deep_free(r);
00299         }
00300         
00301         return names_found;
00302 }
00303 
00304 bool
00305 ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t)
00306 {
00307         switch (ldns_rr_get_type(nsec)) {
00308         case LDNS_RR_TYPE_NSEC  : if (ldns_rr_rd_count(nsec) < 2) {
00309                                           return false;
00310                                   }
00311                                   return ldns_nsec_bitmap_covers_type(
00312                                                   ldns_rr_rdf(nsec, 1), t);
00313 
00314         case LDNS_RR_TYPE_NSEC3 : if (ldns_rr_rd_count(nsec) < 6) {
00315                                           return false;
00316                                   }
00317                                   return ldns_nsec_bitmap_covers_type(
00318                                                   ldns_rr_rdf(nsec, 5), t);
00319 
00320         default                 : return false;
00321         }
00322 }
00323 
00324 void
00325 ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
00326 {
00327         int16_t rdf;
00328         ldns_rdf *rd;
00329         va_list va_rdf;
00330         va_start(va_rdf, rdfnum);
00331 
00332         for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 
00333         {
00334                 rd = ldns_rr_rdf(r, rdf);
00335                 if (!rd) {
00336                         continue;
00337                 } else {
00338                         ldns_rdf_print(fp, rd);
00339                         fprintf(fp, " "); /* not sure if we want to do this */
00340                 }
00341         }
00342         va_end(va_rdf);
00343 }
00344