dnssec_zone.c

Go to the documentation of this file.
00001 /*
00002  * special zone file structures and functions for better dnssec handling
00003  */
00004 
00005 #include <ldns/config.h>
00006 
00007 #include <ldns/ldns.h>
00008 
00009 ldns_dnssec_rrs *
00010 ldns_dnssec_rrs_new()
00011 {
00012         ldns_dnssec_rrs *new_rrs;
00013         new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
00014         if(!new_rrs) return NULL;
00015         new_rrs->rr = NULL;
00016         new_rrs->next = NULL;
00017         return new_rrs;
00018 }
00019 
00020 INLINE void
00021 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
00022 {
00023         ldns_dnssec_rrs *next;
00024         while (rrs) {
00025                 next = rrs->next;
00026                 if (deep) {
00027                         ldns_rr_free(rrs->rr);
00028                 }
00029                 LDNS_FREE(rrs);
00030                 rrs = next;
00031         }
00032 }
00033 
00034 void
00035 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
00036 {
00037         ldns_dnssec_rrs_free_internal(rrs, 0);
00038 }
00039 
00040 void
00041 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
00042 {
00043         ldns_dnssec_rrs_free_internal(rrs, 1);
00044 }
00045 
00046 ldns_status
00047 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
00048 {
00049         int cmp;
00050         ldns_dnssec_rrs *new_rrs;
00051         if (!rrs || !rr) {
00052                 return LDNS_STATUS_ERR;
00053         }
00054 
00055         /* this could be done more efficiently; name and type should already
00056            be equal */
00057         cmp = ldns_rr_compare(rrs->rr,
00058                                           rr);
00059         /* should we error on equal? */
00060         if (cmp <= 0) {
00061                 if (rrs->next) {
00062                         return ldns_dnssec_rrs_add_rr(rrs->next, rr);
00063                 } else {
00064                         new_rrs = ldns_dnssec_rrs_new();
00065                         new_rrs->rr = rr;
00066                         rrs->next = new_rrs;
00067                 }
00068         } else if (cmp > 0) {
00069                 /* put the current old rr in the new next, put the new
00070                    rr in the current container */
00071                 new_rrs = ldns_dnssec_rrs_new();
00072                 new_rrs->rr = rrs->rr;
00073                 new_rrs->next = rrs->next;
00074                 rrs->rr = rr;
00075                 rrs->next = new_rrs;
00076         }
00077         return LDNS_STATUS_OK;
00078 }
00079 
00080 void
00081 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
00082                ldns_dnssec_rrs *rrs)
00083 {
00084         if (!rrs) {
00085                 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00086                         fprintf(out, "; <void>");
00087         } else {
00088                 if (rrs->rr) {
00089                         ldns_rr_print_fmt(out, fmt, rrs->rr);
00090                 }
00091                 if (rrs->next) {
00092                         ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
00093                 }
00094         }
00095 }
00096 
00097 void
00098 ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
00099 {
00100         ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
00101 }
00102 
00103 
00104 ldns_dnssec_rrsets *
00105 ldns_dnssec_rrsets_new()
00106 {
00107         ldns_dnssec_rrsets *new_rrsets;
00108         new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
00109         if(!new_rrsets) return NULL;
00110         new_rrsets->rrs = NULL;
00111         new_rrsets->type = 0;
00112         new_rrsets->signatures = NULL;
00113         new_rrsets->next = NULL;
00114         return new_rrsets;
00115 }
00116 
00117 INLINE void
00118 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
00119 {
00120         if (rrsets) {
00121                 if (rrsets->rrs) {
00122                         ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
00123                 }
00124                 if (rrsets->next) {
00125                         ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
00126                 }
00127                 if (rrsets->signatures) {
00128                         ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
00129                 }
00130                 LDNS_FREE(rrsets);
00131         }
00132 }
00133 
00134 void
00135 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
00136 {
00137         ldns_dnssec_rrsets_free_internal(rrsets, 0);
00138 }
00139 
00140 void
00141 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
00142 {
00143         ldns_dnssec_rrsets_free_internal(rrsets, 1);
00144 }
00145 
00146 ldns_rr_type
00147 ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
00148 {
00149         if (rrsets) {
00150                 return rrsets->type;
00151         } else {
00152                 return 0;
00153         }
00154 }
00155 
00156 ldns_status
00157 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
00158                                            ldns_rr_type type)
00159 {
00160         if (rrsets) {
00161                 rrsets->type = type;
00162                 return LDNS_STATUS_OK;
00163         }
00164         return LDNS_STATUS_ERR;
00165 }
00166 
00167 ldns_dnssec_rrsets *
00168 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
00169 {
00170         ldns_dnssec_rrsets *new_rrsets;
00171         ldns_rr_type rr_type;
00172         bool rrsig;
00173 
00174         new_rrsets = ldns_dnssec_rrsets_new();
00175         rr_type = ldns_rr_get_type(rr);
00176         if (rr_type == LDNS_RR_TYPE_RRSIG) {
00177                 rrsig = true;
00178                 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
00179         } else {
00180                 rrsig = false;
00181         }
00182         if (!rrsig) {
00183                 new_rrsets->rrs = ldns_dnssec_rrs_new();
00184                 new_rrsets->rrs->rr = rr;
00185         } else {
00186                 new_rrsets->signatures = ldns_dnssec_rrs_new();
00187                 new_rrsets->signatures->rr = rr;
00188         }
00189         new_rrsets->type = rr_type;
00190         return new_rrsets;
00191 }
00192 
00193 ldns_status
00194 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
00195 {
00196         ldns_dnssec_rrsets *new_rrsets;
00197         ldns_rr_type rr_type;
00198         bool rrsig = false;
00199         ldns_status result = LDNS_STATUS_OK;
00200 
00201         if (!rrsets || !rr) {
00202                 return LDNS_STATUS_ERR;
00203         }
00204 
00205         rr_type = ldns_rr_get_type(rr);
00206 
00207         if (rr_type == LDNS_RR_TYPE_RRSIG) {
00208                 rrsig = true;
00209                 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
00210         }
00211 
00212         if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
00213                 if (!rrsig) {
00214                         rrsets->rrs = ldns_dnssec_rrs_new();
00215                         rrsets->rrs->rr = rr;
00216                         rrsets->type = rr_type;
00217                 } else {
00218                         rrsets->signatures = ldns_dnssec_rrs_new();
00219                         rrsets->signatures->rr = rr;
00220                         rrsets->type = rr_type;
00221                 }
00222                 return LDNS_STATUS_OK;
00223         }
00224 
00225         if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
00226                 if (rrsets->next) {
00227                         result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
00228                 } else {
00229                         new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
00230                         rrsets->next = new_rrsets;
00231                 }
00232         } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
00233                 /* move the current one into the new next, 
00234                    replace field of current with data from new rr */
00235                 new_rrsets = ldns_dnssec_rrsets_new();
00236                 new_rrsets->rrs = rrsets->rrs;
00237                 new_rrsets->type = rrsets->type;
00238                 new_rrsets->signatures = rrsets->signatures;
00239                 new_rrsets->next = rrsets->next;
00240                 if (!rrsig) {
00241                         rrsets->rrs = ldns_dnssec_rrs_new();
00242                         rrsets->rrs->rr = rr;
00243                         rrsets->signatures = NULL;
00244                 } else {
00245                         rrsets->rrs = NULL;
00246                         rrsets->signatures = ldns_dnssec_rrs_new();
00247                         rrsets->signatures->rr = rr;
00248                 }
00249                 rrsets->type = rr_type;
00250                 rrsets->next = new_rrsets;
00251         } else {
00252                 /* equal, add to current rrsets */
00253                 if (rrsig) {
00254                         if (rrsets->signatures) {
00255                                 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
00256                         } else {
00257                                 rrsets->signatures = ldns_dnssec_rrs_new();
00258                                 rrsets->signatures->rr = rr;
00259                         }
00260                 } else {
00261                         if (rrsets->rrs) {
00262                                 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
00263                         } else {
00264                                 rrsets->rrs = ldns_dnssec_rrs_new();
00265                                 rrsets->rrs->rr = rr;
00266                         }
00267                 }
00268         }
00269 
00270         return result;
00271 }
00272 
00273 void
00274 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
00275                 ldns_dnssec_rrsets *rrsets,
00276                 bool follow,
00277                 bool show_soa)
00278 {
00279         if (!rrsets) {
00280                 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00281                         fprintf(out, "; <void>\n");
00282         } else {
00283                 if (rrsets->rrs &&
00284                     (show_soa ||
00285                         ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
00286                     )
00287                    ) {
00288                         ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
00289                         if (rrsets->signatures) {
00290                                 ldns_dnssec_rrs_print_fmt(out, fmt, 
00291                                                 rrsets->signatures);
00292                         }
00293                 }
00294                 if (follow && rrsets->next) {
00295                         ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 
00296                                         rrsets->next, follow, show_soa);
00297                 }
00298         }
00299 }
00300 
00301 void
00302 ldns_dnssec_rrsets_print_soa(FILE *out,
00303                 ldns_dnssec_rrsets *rrsets,
00304                 bool follow,
00305                 bool show_soa)
00306 {
00307         ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default,
00308                         rrsets, follow, show_soa);
00309 }
00310 
00311 
00312 void
00313 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
00314                 ldns_dnssec_rrsets *rrsets, 
00315                 bool follow)
00316 {
00317         ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
00318 }
00319 
00320 void
00321 ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
00322 {
00323         ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 
00324                         rrsets, follow);
00325 }
00326 
00327 ldns_dnssec_name *
00328 ldns_dnssec_name_new()
00329 {
00330         ldns_dnssec_name *new_name;
00331 
00332         new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
00333         if (!new_name) {
00334                 return NULL;
00335         }
00336         /*
00337          * not needed anymore because CALLOC initalizes everything to zero.
00338 
00339         new_name->name = NULL;
00340         new_name->rrsets = NULL;
00341         new_name->name_alloced = false;
00342         new_name->nsec = NULL;
00343         new_name->nsec_signatures = NULL;
00344 
00345         new_name->is_glue = false;
00346         new_name->hashed_name = NULL;
00347 
00348          */
00349         return new_name;
00350 }
00351 
00352 ldns_dnssec_name *
00353 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
00354 {
00355         ldns_dnssec_name *new_name = ldns_dnssec_name_new();
00356 
00357         new_name->name = ldns_rr_owner(rr);
00358         if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
00359                 ldns_dnssec_name_free(new_name);
00360                 return NULL;
00361         }
00362 
00363         return new_name;
00364 }
00365 
00366 INLINE void
00367 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
00368                                int deep)
00369 {
00370         if (name) {
00371                 if (name->name_alloced) {
00372                         ldns_rdf_deep_free(name->name);
00373                 }
00374                 if (name->rrsets) {
00375                         ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
00376                 }
00377                 if (name->nsec && deep) {
00378                         ldns_rr_free(name->nsec);
00379                 }
00380                 if (name->nsec_signatures) {
00381                         ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
00382                 }
00383                 if (name->hashed_name) {
00384                         if (deep) {
00385                                 ldns_rdf_deep_free(name->hashed_name);
00386                         }
00387                 }
00388                 LDNS_FREE(name);
00389         }
00390 }
00391 
00392 void
00393 ldns_dnssec_name_free(ldns_dnssec_name *name)
00394 {
00395   ldns_dnssec_name_free_internal(name, 0);
00396 }
00397 
00398 void
00399 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
00400 {
00401   ldns_dnssec_name_free_internal(name, 1);
00402 }
00403 
00404 ldns_rdf *
00405 ldns_dnssec_name_name(ldns_dnssec_name *name)
00406 {
00407         if (name) {
00408                 return name->name;
00409         }
00410         return NULL;
00411 }
00412 
00413 bool
00414 ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
00415 {
00416         if (name) {
00417                 return name->is_glue;
00418         }
00419         return false;
00420 }
00421 
00422 void
00423 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
00424                                          ldns_rdf *dname)
00425 {
00426         if (rrset && dname) {
00427                 rrset->name = dname;
00428         }
00429 }
00430 
00431 ldns_rr *
00432 ldns_dnssec_name_nsec(ldns_dnssec_name *rrset)
00433 {
00434         if (rrset) {
00435                 return rrset->nsec;
00436         }
00437         return NULL;
00438 }
00439 
00440 void
00441 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
00442 {
00443         if (rrset && nsec) {
00444                 rrset->nsec = nsec;
00445         }
00446 }
00447 
00448 int
00449 ldns_dnssec_name_cmp(const void *a, const void *b)
00450 {
00451         ldns_dnssec_name *na = (ldns_dnssec_name *) a;
00452         ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
00453 
00454         if (na && nb) {
00455                 return ldns_dname_compare(ldns_dnssec_name_name(na),
00456                                                          ldns_dnssec_name_name(nb));
00457         } else if (na) {
00458                 return 1;
00459         } else if (nb) {
00460                 return -1;
00461         } else {
00462                 return 0;
00463         }
00464 }
00465 
00466 ldns_status
00467 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
00468                                     ldns_rr *rr)
00469 {
00470         ldns_status result = LDNS_STATUS_OK;
00471         ldns_rdf *name_name;
00472         bool hashed_name = false;
00473         ldns_rr_type rr_type;
00474         ldns_rr_type typecovered = 0;
00475 
00476         /* special handling for NSEC3 and NSECX covering RRSIGS */
00477 
00478         if (!name || !rr) {
00479                 return LDNS_STATUS_ERR;
00480         }
00481 
00482         rr_type = ldns_rr_get_type(rr);
00483 
00484         if (rr_type == LDNS_RR_TYPE_RRSIG) {
00485                 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
00486         }
00487 
00488 #ifdef HAVE_SSL
00489         if (rr_type == LDNS_RR_TYPE_NSEC3 ||
00490             typecovered == LDNS_RR_TYPE_NSEC3) {
00491                 name_name = ldns_nsec3_hash_name_frm_nsec3(rr,
00492                                                                                    ldns_dnssec_name_name(name));
00493                 hashed_name = true;
00494         } else {
00495                 name_name = ldns_dnssec_name_name(name);
00496         }
00497 #else
00498         name_name = ldns_dnssec_name_name(name);
00499 #endif /* HAVE_SSL */
00500 
00501         if (rr_type == LDNS_RR_TYPE_NSEC ||
00502             rr_type == LDNS_RR_TYPE_NSEC3) {
00503                 /* XX check if is already set (and error?) */
00504                 name->nsec = rr;
00505         } else if (typecovered == LDNS_RR_TYPE_NSEC ||
00506                          typecovered == LDNS_RR_TYPE_NSEC3) {
00507                 if (name->nsec_signatures) {
00508                         result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
00509                 } else {
00510                         name->nsec_signatures = ldns_dnssec_rrs_new();
00511                         name->nsec_signatures->rr = rr;
00512                 }
00513         } else {
00514                 /* it's a 'normal' RR, add it to the right rrset */
00515                 if (name->rrsets) {
00516                         result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
00517                 } else {
00518                         name->rrsets = ldns_dnssec_rrsets_new();
00519                         result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
00520                 }
00521         }
00522 
00523         if (hashed_name) {
00524                 ldns_rdf_deep_free(name_name);
00525         }
00526 
00527         return result;
00528 }
00529 
00530 ldns_dnssec_rrsets *
00531 ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
00532                                            ldns_rr_type type) {
00533         ldns_dnssec_rrsets *result;
00534 
00535         result = name->rrsets;
00536         while (result) {
00537                 if (result->type == type) {
00538                         return result;
00539                 } else {
00540                         result = result->next;
00541                 }
00542         }
00543         return NULL;
00544 }
00545 
00546 ldns_dnssec_rrsets *
00547 ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
00548                                            ldns_rdf *dname,
00549                                            ldns_rr_type type)
00550 {
00551         ldns_rbnode_t *node;
00552 
00553         if (!zone || !dname) {
00554                 return NULL;
00555         }
00556 
00557         node = ldns_rbtree_search(zone->names, dname);
00558         if (node) {
00559                 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
00560                                                                         type);
00561         } else {
00562                 return NULL;
00563         }
00564 }
00565 
00566 void
00567 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
00568                 ldns_dnssec_name *name, 
00569                 bool show_soa)
00570 {
00571         if (name) {
00572                 if(name->rrsets) {
00573                         ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 
00574                                         name->rrsets, true, show_soa);
00575                 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
00576                         fprintf(out, ";; Empty nonterminal: ");
00577                         ldns_rdf_print(out, name->name);
00578                         fprintf(out, "\n");
00579                 }
00580                 if(name->nsec) {
00581                         ldns_rr_print_fmt(out, fmt, name->nsec);
00582                 }
00583                 if (name->nsec_signatures) {
00584                         ldns_dnssec_rrs_print_fmt(out, fmt, 
00585                                         name->nsec_signatures);
00586                 }
00587         } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
00588                 fprintf(out, "; <void>\n");
00589         }
00590 }
00591 
00592 void
00593 ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
00594 {
00595         ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default,
00596                        name, show_soa);
00597 }
00598 
00599 void
00600 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
00601                 ldns_dnssec_name *name)
00602 {
00603         ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
00604 }
00605 
00606 void
00607 ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
00608 {
00609         ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
00610 }
00611 
00612 
00613 ldns_dnssec_zone *
00614 ldns_dnssec_zone_new()
00615 {
00616         ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
00617         if(!zone) return NULL;
00618         zone->soa = NULL;
00619         zone->names = NULL;
00620 
00621         return zone;
00622 }
00623 
00624 void
00625 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
00626         (void) arg;
00627         ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
00628         free(node);
00629 }
00630 
00631 void
00632 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
00633         (void) arg;
00634         ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
00635         free(node);
00636 }
00637 
00638 void
00639 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
00640 {
00641         if (zone) {
00642                 if (zone->names) {
00643                         /* destroy all name structures within the tree */
00644                         ldns_traverse_postorder(zone->names,
00645                                                     ldns_dnssec_name_node_free,
00646                                                     NULL);
00647                         free(zone->names);
00648                 }
00649                 LDNS_FREE(zone);
00650         }
00651 }
00652 
00653 void
00654 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
00655 {
00656         if (zone) {
00657                 if (zone->names) {
00658                         /* destroy all name structures within the tree */
00659                         ldns_traverse_postorder(zone->names,
00660                                                     ldns_dnssec_name_node_deep_free,
00661                                                     NULL);
00662                         free(zone->names);
00663                 }
00664                 LDNS_FREE(zone);
00665         }
00666 }
00667 
00668 /* use for dname comparison in tree */
00669 int
00670 ldns_dname_compare_v(const void *a, const void *b) {
00671         return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
00672 }
00673 
00674 #ifdef HAVE_SSL
00675 ldns_rbnode_t *
00676 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
00677                                      ldns_rr *rr) {
00678         ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
00679         ldns_dnssec_name *current_name;
00680         ldns_rdf *hashed_name;
00681 
00682         hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
00683 
00684         while (current_node != LDNS_RBTREE_NULL) {
00685                 current_name = (ldns_dnssec_name *) current_node->data;
00686                 if (!current_name->hashed_name) {
00687                         current_name->hashed_name =
00688                                 ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
00689                 }
00690                 if (ldns_dname_compare(hashed_name,
00691                                                    current_name->hashed_name)
00692                     == 0) {
00693                         ldns_rdf_deep_free(hashed_name);
00694                         return current_node;
00695                 }
00696                 current_node = ldns_rbtree_next(current_node);
00697         }
00698         ldns_rdf_deep_free(hashed_name);
00699         return NULL;
00700 }
00701 
00702 ldns_status
00703 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
00704 {
00705         ldns_status result = LDNS_STATUS_OK;
00706         ldns_dnssec_name *cur_name;
00707         ldns_rbnode_t *cur_node;
00708         ldns_rr_type type_covered = 0;
00709 
00710         if (!zone || !rr) {
00711                 return LDNS_STATUS_ERR;
00712         }
00713 
00714         if (!zone->names) {
00715                 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
00716                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
00717         }
00718 
00719         /* we need the original of the hashed name if this is
00720            an NSEC3, or an RRSIG that covers an NSEC3 */
00721         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
00722                 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
00723         }
00724         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
00725             type_covered == LDNS_RR_TYPE_NSEC3) {
00726                 cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
00727                                                                                            rr);
00728                 if (!cur_node) {
00729                         return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
00730                 }
00731         } else {
00732                 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
00733         }
00734 
00735         if (!cur_node) {
00736                 /* add */
00737                 cur_name = ldns_dnssec_name_new_frm_rr(rr);
00738                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
00739                 cur_node = LDNS_MALLOC(ldns_rbnode_t);
00740                 if(!cur_node) {
00741                         ldns_dnssec_name_free(cur_name);
00742                         return LDNS_STATUS_MEM_ERR;
00743                 }
00744                 cur_node->key = ldns_rr_owner(rr);
00745                 cur_node->data = cur_name;
00746                 (void)ldns_rbtree_insert(zone->names, cur_node);
00747         } else {
00748                 cur_name = (ldns_dnssec_name *) cur_node->data;
00749                 result = ldns_dnssec_name_add_rr(cur_name, rr);
00750         }
00751 
00752         if (result != LDNS_STATUS_OK) {
00753                 fprintf(stderr, "error adding rr: ");
00754                 ldns_rr_print(stderr, rr);
00755         }
00756 
00757         /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
00758         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
00759                 zone->soa = cur_name;
00760         }
00761 
00762         return result;
00763 }
00764 #endif /* HAVE_SSL */
00765 
00766 void
00767 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
00768                 ldns_rbtree_t *tree, 
00769                 bool print_soa)
00770 {
00771         ldns_rbnode_t *node;
00772         ldns_dnssec_name *name;
00773 
00774         node = ldns_rbtree_first(tree);
00775         while (node != LDNS_RBTREE_NULL) {
00776                 name = (ldns_dnssec_name *) node->data;
00777                 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
00778                 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00779                         fprintf(out, ";\n");
00780                 node = ldns_rbtree_next(node);
00781         }
00782 }
00783 
00784 void
00785 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
00786 {
00787         ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
00788                        tree, print_soa);
00789 }
00790 
00791 void
00792 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
00793                ldns_dnssec_zone *zone)
00794 {
00795         if (zone) {
00796                 if (zone->soa) {
00797                         if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
00798                                 fprintf(out, ";; Zone: ");
00799                                 ldns_rdf_print(out, ldns_dnssec_name_name(
00800                                                         zone->soa));
00801                                 fprintf(out, "\n;\n");
00802                         }
00803                         ldns_dnssec_rrsets_print_fmt(out, fmt,
00804                                         ldns_dnssec_name_find_rrset(
00805                                                 zone->soa, 
00806                                                 LDNS_RR_TYPE_SOA), 
00807                                         false);
00808                         if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00809                                 fprintf(out, ";\n");
00810                 }
00811 
00812                 if (zone->names) {
00813                         ldns_dnssec_zone_names_print_fmt(out, fmt, 
00814                                         zone->names, false);
00815                 }
00816         }
00817 }
00818 
00819 void
00820 ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
00821 {
00822         ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
00823 }
00824 
00825 ldns_status
00826 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
00827 {
00828         ldns_dnssec_name *new_name;
00829         ldns_rdf *cur_name;
00830         ldns_rdf *next_name;
00831         ldns_rbnode_t *cur_node, *next_node, *new_node;
00832 
00833         /* for the detection */
00834         uint16_t i, cur_label_count, next_label_count;
00835         uint16_t soa_label_count = 0;
00836         ldns_rdf *l1, *l2;
00837         int lpos;
00838 
00839         if (!zone) {
00840                 return LDNS_STATUS_ERR;
00841         }
00842         if (zone->soa && zone->soa->name) {
00843                 soa_label_count = ldns_dname_label_count(zone->soa->name);
00844         }
00845         
00846         cur_node = ldns_rbtree_first(zone->names);
00847         while (cur_node != LDNS_RBTREE_NULL) {
00848                 next_node = ldns_rbtree_next(cur_node);
00849                 
00850                 /* skip glue */
00851                 while (next_node != LDNS_RBTREE_NULL && 
00852                        next_node->data &&
00853                        ((ldns_dnssec_name *)next_node->data)->is_glue
00854                 ) {
00855                         next_node = ldns_rbtree_next(next_node);
00856                 }
00857 
00858                 if (next_node == LDNS_RBTREE_NULL) {
00859                         next_node = ldns_rbtree_first(zone->names);
00860                 }
00861 
00862                 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
00863                 next_name = ((ldns_dnssec_name *)next_node->data)->name;
00864                 cur_label_count = ldns_dname_label_count(cur_name);
00865                 next_label_count = ldns_dname_label_count(next_name);
00866 
00867                 /* Since the names are in canonical order, we can
00868                  * recognize empty non-terminals by their labels;
00869                  * every label after the first one on the next owner
00870                  * name is a non-terminal if it either does not exist
00871                  * in the current name or is different from the same
00872                  * label in the current name (counting from the end)
00873                  */
00874                 for (i = 1; i < next_label_count - soa_label_count; i++) {
00875                         lpos = (int)cur_label_count - (int)next_label_count + (int)i;
00876                         if (lpos >= 0) {
00877                                 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
00878                         } else {
00879                                 l1 = NULL;
00880                         }
00881                         l2 = ldns_dname_clone_from(next_name, i);
00882 
00883                         if (!l1 || ldns_dname_compare(l1, l2) != 0) {
00884                                 /* We have an empty nonterminal, add it to the
00885                                  * tree
00886                                  */
00887                                 new_name = ldns_dnssec_name_new();
00888                                 if (!new_name) {
00889                                         return LDNS_STATUS_MEM_ERR;
00890                                 }
00891                                 new_name->name = ldns_dname_clone_from(next_name,
00892                                                                        i);
00893                                 if (!new_name->name) {
00894                                         ldns_dnssec_name_free(new_name);
00895                                         return LDNS_STATUS_MEM_ERR;
00896                                 }
00897                                 new_name->name_alloced = true;
00898                                 new_node = LDNS_MALLOC(ldns_rbnode_t);
00899                                 if (!new_node) {
00900                                         ldns_dnssec_name_free(new_name);
00901                                         return LDNS_STATUS_MEM_ERR;
00902                                 }
00903                                 new_node->key = new_name->name;
00904                                 new_node->data = new_name;
00905                                 (void)ldns_rbtree_insert(zone->names, new_node);
00906                         }
00907                         ldns_rdf_deep_free(l1);
00908                         ldns_rdf_deep_free(l2);
00909                 }
00910                 
00911                 /* we might have inserted a new node after
00912                  * the current one so we can't just use next()
00913                  */
00914                 if (next_node != ldns_rbtree_first(zone->names)) {
00915                         cur_node = next_node;
00916                 } else {
00917                         cur_node = LDNS_RBTREE_NULL;
00918                 }
00919         }
00920         return LDNS_STATUS_OK;
00921 }

Generated on Thu Apr 5 23:03:54 2012 for ldns by  doxygen 1.4.7