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         if (pkt) {
00130                 /* extract the data we need */
00131                 names = ldns_pkt_rr_list_by_type(pkt, 
00132                                 LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER);
00133         }
00134         return names;
00135 }
00136 
00137 /* read a line, put it in a buffer, parse the buffer */
00138 ldns_rr_list *
00139 ldns_get_rr_list_hosts_frm_fp(FILE *fp)
00140 {
00141         return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
00142 }
00143 
00144 ldns_rr_list *
00145 ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
00146 {
00147         ssize_t i, j;
00148         size_t cnt;
00149         char *line;
00150         char *word;
00151         char *addr;
00152         char *rr_str;
00153         ldns_buffer *linebuf;
00154         ldns_rr *rr;
00155         ldns_rr_list *list;
00156         ldns_rdf *tmp;
00157         bool ip6;
00158         ldns_status parse_result;
00159 
00160         line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00161         word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00162         addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00163         rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
00164         ip6 = false;
00165         list = ldns_rr_list_new();
00166         rr = NULL;
00167         if(!line || !word || !addr || !rr_str || !list) {
00168                 LDNS_FREE(line);
00169                 LDNS_FREE(word);
00170                 LDNS_FREE(addr);
00171                 LDNS_FREE(rr_str);
00172                 ldns_rr_list_free(list);
00173                 return NULL;
00174         }
00175 
00176         for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
00177                         i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
00178                 /* # is comment */
00179                 if (line[0] == '#') {
00180                         continue;
00181                 }
00182                 /* put it in a buffer for further processing */
00183                 linebuf = LDNS_MALLOC(ldns_buffer);
00184                 if(!linebuf) {
00185                         LDNS_FREE(line);
00186                         LDNS_FREE(word);
00187                         LDNS_FREE(addr);
00188                         LDNS_FREE(rr_str);
00189                         ldns_rr_list_deep_free(list);
00190                         return NULL;
00191                 }
00192 
00193                 ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
00194                 for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
00195                                 j > 0;
00196                                 j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
00197                         if (cnt == 0) {
00198                                 /* the address */
00199                                 if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 
00200                                                                 word))) {
00201                                         /* ip6 */
00202                                         ldns_rdf_deep_free(tmp);
00203                                         ip6 = true;
00204                                 } else {
00205                                         if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 
00206                                                                         word))) {
00207                                                 /* ip4 */
00208                                                 ldns_rdf_deep_free(tmp);
00209                                                 ip6 = false;
00210                                         } else {
00211                                                 /* kaput */
00212                                                 break;
00213                                         }
00214                                 }
00215                                 (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
00216                         } else {
00217                                 /* la al la la */
00218                                 if (ip6) {
00219                                         snprintf(rr_str, LDNS_MAX_LINELEN, 
00220                                                 "%s IN AAAA %s", word, addr);
00221                                 } else {
00222                                         snprintf(rr_str, LDNS_MAX_LINELEN, 
00223                                                 "%s IN A %s", word, addr);
00224                                 }
00225                                 parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
00226                                 if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
00227                                         ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
00228                                 }
00229                                 ldns_rr_free(rr);
00230                         }
00231                 }
00232                 ldns_buffer_free(linebuf);
00233         }
00234         LDNS_FREE(line);
00235         LDNS_FREE(word);
00236         LDNS_FREE(addr);
00237         LDNS_FREE(rr_str);
00238         return list;
00239 }
00240 
00241 ldns_rr_list *
00242 ldns_get_rr_list_hosts_frm_file(char *filename)
00243 {
00244         ldns_rr_list *names;
00245         FILE *fp;
00246 
00247         if (!filename) {
00248                 fp = fopen(LDNS_RESOLV_HOSTS, "r");
00249         
00250         } else {
00251                 fp = fopen(filename, "r");
00252         }
00253         if (!fp) {
00254                 return NULL;
00255         }
00256 
00257         names = ldns_get_rr_list_hosts_frm_fp(fp);
00258         fclose(fp);
00259         return names;
00260 }
00261 
00262 uint16_t
00263 ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 
00264                 ldns_rr_list **ret)
00265 {
00266         ldns_rdf_type t;
00267         uint16_t names_found;
00268         ldns_resolver *r;
00269         ldns_status s;
00270 
00271         t = ldns_rdf_get_type(node);
00272         names_found = 0;
00273         r = res;
00274 
00275         if (res == NULL) {
00276                 /* prepare a new resolver, using /etc/resolv.conf as a guide  */
00277                 s = ldns_resolver_new_frm_file(&r, NULL);
00278                 if (s != LDNS_STATUS_OK) {
00279                         return 0;
00280                 } 
00281         }
00282 
00283         if (t == LDNS_RDF_TYPE_DNAME) {
00284                 /* we're asked to query for a name */
00285                 *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
00286                 names_found = ldns_rr_list_rr_count(*ret);
00287         }
00288 
00289         if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
00290                 /* an address */
00291                 *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
00292                 names_found = ldns_rr_list_rr_count(*ret);
00293         }
00294 
00295         if (res == NULL) {
00296                 ldns_resolver_deep_free(r);
00297         }
00298         
00299         return names_found;
00300 }
00301 
00302 bool
00303 ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t)
00304 {
00305         /* does the nsec cover the t given? */
00306         /* copied from host2str.c line 465: ldns_rdf2buffer_str_nsec */
00307         uint8_t window_block_nr;
00308         uint8_t bitmap_length;
00309         uint16_t type;
00310         uint16_t pos = 0;
00311         uint16_t bit_pos;
00312         ldns_rdf *nsec_type_list = ldns_rr_rdf(nsec, 1); 
00313         uint8_t *data;
00314         
00315         if (nsec_type_list == NULL) {
00316                 return false;
00317         }
00318         data  = ldns_rdf_data(nsec_type_list);
00319 
00320         while(pos < ldns_rdf_size(nsec_type_list)) {
00321                 window_block_nr = data[pos];
00322                 bitmap_length = data[pos + 1];
00323                 pos += 2;
00324 
00325                 for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
00326                         if (ldns_get_bit(&data[pos], bit_pos)) {
00327                                 type = 256 * (uint16_t) window_block_nr + bit_pos;
00328 
00329                                 if ((ldns_rr_type)type == t) {
00330                                         /* we have a winner */
00331                                         return true;
00332                                 }
00333                         }
00334                 }
00335                 pos += (uint16_t) bitmap_length;
00336         }
00337         return false;
00338 }
00339 
00340 void
00341 ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
00342 {
00343         int16_t rdf;
00344         ldns_rdf *rd;
00345         va_list va_rdf;
00346         va_start(va_rdf, rdfnum);
00347 
00348         for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 
00349         {
00350                 rd = ldns_rr_rdf(r, rdf);
00351                 if (!rd) {
00352                         continue;
00353                 } else {
00354                         ldns_rdf_print(fp, rd);
00355                         fprintf(fp, " "); /* not sure if we want to do this */
00356                 }
00357         }
00358         va_end(va_rdf);
00359 }

Generated on Fri Jun 8 17:07:02 2012 for ldns by  doxygen 1.4.7