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 static bool
00625 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
00626 {
00627         return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
00628                 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
00629 }
00630 
00631 /* When the zone is first read into an list and then inserted into an
00632  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
00633  * to each other. Because ldns-verify-zone (the only program that uses this
00634  * function) uses the rbtree mostly for sequentual walking, this results
00635  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
00636  */
00637 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
00638 
00639 ldns_status
00640 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
00641                 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
00642 {
00643         ldns_rr* cur_rr;
00644         size_t i;
00645 
00646         ldns_rdf *my_origin = NULL;
00647         ldns_rdf *my_prev = NULL;
00648 
00649         ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
00650         /* when reading NSEC3s, there is a chance that we encounter nsecs
00651            for empty nonterminals, whose nonterminals we cannot derive yet
00652            because the needed information is to be read later. in that case
00653            we keep a list of those nsec3's and retry to add them later */
00654         ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
00655         ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
00656 
00657         ldns_status status = LDNS_STATUS_MEM_ERR;
00658 
00659 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
00660         ldns_zone* zone = NULL;
00661         if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
00662                         != LDNS_STATUS_OK) goto error;
00663 #else
00664         uint32_t  my_ttl = ttl;
00665 #endif
00666 
00667         if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
00668 
00669         if (origin) {
00670                 if (!(my_origin = ldns_rdf_clone(origin))) goto error;
00671                 if (!(my_prev   = ldns_rdf_clone(origin))) goto error;
00672         }
00673 
00674 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
00675         if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
00676                         != LDNS_STATUS_OK) goto error;
00677 
00678         for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
00679                 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
00680                 status = LDNS_STATUS_OK;
00681 #else
00682         while (!feof(fp)) {
00683                 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
00684                                 &my_prev, line_nr);
00685 
00686 #endif
00687                 switch (status) {
00688                 case LDNS_STATUS_OK:
00689 
00690                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
00691                         if (status ==
00692                                 LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
00693 
00694                                 if (rr_is_rrsig_covering(cur_rr,
00695                                                         LDNS_RR_TYPE_NSEC3)){
00696                                         ldns_rr_list_push_rr(todo_nsec3_rrsigs,
00697                                                         cur_rr);
00698                                 } else {
00699                                         ldns_rr_list_push_rr(todo_nsec3s,
00700                                                         cur_rr);
00701                                 }
00702                         } else if (status != LDNS_STATUS_OK)
00703                                 goto error;
00704 
00705                         break;
00706 
00707 
00708                 case LDNS_STATUS_SYNTAX_EMPTY:  /* empty line was seen */
00709                 case LDNS_STATUS_SYNTAX_TTL:    /* the ttl was set*/
00710                 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
00711                         break;
00712 
00713                 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
00714                         status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
00715                         break;
00716 
00717                 default:
00718                         goto error;
00719                 }
00720         }
00721 
00722         if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
00723                 (void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
00724                 for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
00725                         cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
00726                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
00727                 }
00728                 for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){
00729                         cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
00730                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
00731                 }
00732         } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
00733                 for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){
00734                         cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
00735                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
00736                 }
00737         }
00738 
00739         ldns_rr_list_free(todo_nsec3_rrsigs);
00740         ldns_rr_list_free(todo_nsec3s);
00741 
00742         if (z) {
00743                 *z = newzone;
00744         } else {
00745                 ldns_dnssec_zone_free(newzone);
00746         }
00747 
00748         return LDNS_STATUS_OK;
00749 
00750 error:
00751 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
00752         if (zone) {
00753                 ldns_zone_free(zone);
00754         }
00755 #endif
00756         if (my_origin) {
00757                 ldns_rdf_deep_free(my_origin);
00758         }
00759         if (my_prev) {
00760                 ldns_rdf_deep_free(my_prev);
00761         }
00762         if (newzone) {
00763                 ldns_dnssec_zone_free(newzone);
00764         }
00765         return status;
00766 }
00767 
00768 ldns_status
00769 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
00770                 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
00771 {
00772         return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
00773 }
00774 
00775 void
00776 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
00777         (void) arg;
00778         ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
00779         LDNS_FREE(node);
00780 }
00781 
00782 void
00783 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
00784         (void) arg;
00785         ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
00786         LDNS_FREE(node);
00787 }
00788 
00789 void
00790 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
00791 {
00792         if (zone) {
00793                 if (zone->names) {
00794                         /* destroy all name structures within the tree */
00795                         ldns_traverse_postorder(zone->names,
00796                                                     ldns_dnssec_name_node_free,
00797                                                     NULL);
00798                         LDNS_FREE(zone->names);
00799                 }
00800                 LDNS_FREE(zone);
00801         }
00802 }
00803 
00804 void
00805 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
00806 {
00807         if (zone) {
00808                 if (zone->names) {
00809                         /* destroy all name structures within the tree */
00810                         ldns_traverse_postorder(zone->names,
00811                                                     ldns_dnssec_name_node_deep_free,
00812                                                     NULL);
00813                         LDNS_FREE(zone->names);
00814                 }
00815                 LDNS_FREE(zone);
00816         }
00817 }
00818 
00819 /* use for dname comparison in tree */
00820 int
00821 ldns_dname_compare_v(const void *a, const void *b) {
00822         return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
00823 }
00824 
00825 #ifdef HAVE_SSL
00826 ldns_rbnode_t *
00827 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
00828                                      ldns_rr *rr) {
00829         ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
00830         ldns_dnssec_name *current_name;
00831         ldns_rdf *hashed_name;
00832 
00833         hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
00834 
00835         while (current_node != LDNS_RBTREE_NULL) {
00836                 current_name = (ldns_dnssec_name *) current_node->data;
00837                 if (!current_name->hashed_name) {
00838                         current_name->hashed_name =
00839                                 ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
00840                 }
00841                 if (ldns_dname_compare(hashed_name,
00842                                                    current_name->hashed_name)
00843                     == 0) {
00844                         ldns_rdf_deep_free(hashed_name);
00845                         return current_node;
00846                 }
00847                 current_node = ldns_rbtree_next(current_node);
00848         }
00849         ldns_rdf_deep_free(hashed_name);
00850         return NULL;
00851 }
00852 
00853 ldns_status
00854 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
00855 {
00856         ldns_status result = LDNS_STATUS_OK;
00857         ldns_dnssec_name *cur_name;
00858         ldns_rbnode_t *cur_node;
00859         ldns_rr_type type_covered = 0;
00860 
00861         if (!zone || !rr) {
00862                 return LDNS_STATUS_ERR;
00863         }
00864 
00865         if (!zone->names) {
00866                 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
00867                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
00868         }
00869 
00870         /* we need the original of the hashed name if this is
00871            an NSEC3, or an RRSIG that covers an NSEC3 */
00872         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
00873                 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
00874         }
00875         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
00876             type_covered == LDNS_RR_TYPE_NSEC3) {
00877                 cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
00878                                                                                            rr);
00879                 if (!cur_node) {
00880                         return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
00881                 }
00882         } else {
00883                 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
00884         }
00885 
00886         if (!cur_node) {
00887                 /* add */
00888                 cur_name = ldns_dnssec_name_new_frm_rr(rr);
00889                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
00890                 cur_node = LDNS_MALLOC(ldns_rbnode_t);
00891                 if(!cur_node) {
00892                         ldns_dnssec_name_free(cur_name);
00893                         return LDNS_STATUS_MEM_ERR;
00894                 }
00895                 cur_node->key = ldns_rr_owner(rr);
00896                 cur_node->data = cur_name;
00897                 (void)ldns_rbtree_insert(zone->names, cur_node);
00898         } else {
00899                 cur_name = (ldns_dnssec_name *) cur_node->data;
00900                 result = ldns_dnssec_name_add_rr(cur_name, rr);
00901         }
00902 
00903         if (result != LDNS_STATUS_OK) {
00904                 fprintf(stderr, "error adding rr: ");
00905                 ldns_rr_print(stderr, rr);
00906         }
00907 
00908         /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
00909         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
00910                 zone->soa = cur_name;
00911         }
00912 
00913         return result;
00914 }
00915 #endif /* HAVE_SSL */
00916 
00917 void
00918 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
00919                 ldns_rbtree_t *tree, 
00920                 bool print_soa)
00921 {
00922         ldns_rbnode_t *node;
00923         ldns_dnssec_name *name;
00924 
00925         node = ldns_rbtree_first(tree);
00926         while (node != LDNS_RBTREE_NULL) {
00927                 name = (ldns_dnssec_name *) node->data;
00928                 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
00929                 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00930                         fprintf(out, ";\n");
00931                 node = ldns_rbtree_next(node);
00932         }
00933 }
00934 
00935 void
00936 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
00937 {
00938         ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
00939                        tree, print_soa);
00940 }
00941 
00942 void
00943 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
00944                ldns_dnssec_zone *zone)
00945 {
00946         if (zone) {
00947                 if (zone->soa) {
00948                         if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
00949                                 fprintf(out, ";; Zone: ");
00950                                 ldns_rdf_print(out, ldns_dnssec_name_name(
00951                                                         zone->soa));
00952                                 fprintf(out, "\n;\n");
00953                         }
00954                         ldns_dnssec_rrsets_print_fmt(out, fmt,
00955                                         ldns_dnssec_name_find_rrset(
00956                                                 zone->soa, 
00957                                                 LDNS_RR_TYPE_SOA), 
00958                                         false);
00959                         if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00960                                 fprintf(out, ";\n");
00961                 }
00962 
00963                 if (zone->names) {
00964                         ldns_dnssec_zone_names_print_fmt(out, fmt, 
00965                                         zone->names, false);
00966                 }
00967         }
00968 }
00969 
00970 void
00971 ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
00972 {
00973         ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
00974 }
00975 
00976 ldns_status
00977 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
00978 {
00979         ldns_dnssec_name *new_name;
00980         ldns_rdf *cur_name;
00981         ldns_rdf *next_name;
00982         ldns_rbnode_t *cur_node, *next_node, *new_node;
00983 
00984         /* for the detection */
00985         uint16_t i, cur_label_count, next_label_count;
00986         uint16_t soa_label_count = 0;
00987         ldns_rdf *l1, *l2;
00988         int lpos;
00989 
00990         if (!zone) {
00991                 return LDNS_STATUS_ERR;
00992         }
00993         if (zone->soa && zone->soa->name) {
00994                 soa_label_count = ldns_dname_label_count(zone->soa->name);
00995         }
00996         
00997         cur_node = ldns_rbtree_first(zone->names);
00998         while (cur_node != LDNS_RBTREE_NULL) {
00999                 next_node = ldns_rbtree_next(cur_node);
01000                 
01001                 /* skip glue */
01002                 while (next_node != LDNS_RBTREE_NULL && 
01003                        next_node->data &&
01004                        ((ldns_dnssec_name *)next_node->data)->is_glue
01005                 ) {
01006                         next_node = ldns_rbtree_next(next_node);
01007                 }
01008 
01009                 if (next_node == LDNS_RBTREE_NULL) {
01010                         next_node = ldns_rbtree_first(zone->names);
01011                 }
01012 
01013                 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
01014                 next_name = ((ldns_dnssec_name *)next_node->data)->name;
01015                 cur_label_count = ldns_dname_label_count(cur_name);
01016                 next_label_count = ldns_dname_label_count(next_name);
01017 
01018                 /* Since the names are in canonical order, we can
01019                  * recognize empty non-terminals by their labels;
01020                  * every label after the first one on the next owner
01021                  * name is a non-terminal if it either does not exist
01022                  * in the current name or is different from the same
01023                  * label in the current name (counting from the end)
01024                  */
01025                 for (i = 1; i < next_label_count - soa_label_count; i++) {
01026                         lpos = (int)cur_label_count - (int)next_label_count + (int)i;
01027                         if (lpos >= 0) {
01028                                 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
01029                         } else {
01030                                 l1 = NULL;
01031                         }
01032                         l2 = ldns_dname_clone_from(next_name, i);
01033 
01034                         if (!l1 || ldns_dname_compare(l1, l2) != 0) {
01035                                 /* We have an empty nonterminal, add it to the
01036                                  * tree
01037                                  */
01038                                 new_name = ldns_dnssec_name_new();
01039                                 if (!new_name) {
01040                                         return LDNS_STATUS_MEM_ERR;
01041                                 }
01042                                 new_name->name = ldns_dname_clone_from(next_name,
01043                                                                        i);
01044                                 if (!new_name->name) {
01045                                         ldns_dnssec_name_free(new_name);
01046                                         return LDNS_STATUS_MEM_ERR;
01047                                 }
01048                                 new_name->name_alloced = true;
01049                                 new_node = LDNS_MALLOC(ldns_rbnode_t);
01050                                 if (!new_node) {
01051                                         ldns_dnssec_name_free(new_name);
01052                                         return LDNS_STATUS_MEM_ERR;
01053                                 }
01054                                 new_node->key = new_name->name;
01055                                 new_node->data = new_name;
01056                                 (void)ldns_rbtree_insert(zone->names, new_node);
01057                         }
01058                         ldns_rdf_deep_free(l1);
01059                         ldns_rdf_deep_free(l2);
01060                 }
01061                 
01062                 /* we might have inserted a new node after
01063                  * the current one so we can't just use next()
01064                  */
01065                 if (next_node != ldns_rbtree_first(zone->names)) {
01066                         cur_node = next_node;
01067                 } else {
01068                         cur_node = LDNS_RBTREE_NULL;
01069                 }
01070         }
01071         return LDNS_STATUS_OK;
01072 }
01073 
01074 bool
01075 ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
01076 {
01077         ldns_rr* nsec3;
01078         ldns_rbnode_t* node;
01079 
01080         if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
01081                 node = ldns_rbtree_first(zone->names);
01082                 while (node != LDNS_RBTREE_NULL) {
01083                         nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
01084                         if (nsec3 &&ldns_rr_get_type(nsec3) 
01085                                         == LDNS_RR_TYPE_NSEC3 &&
01086                                         ldns_nsec3_optout(nsec3)) {
01087                                 return true;
01088                         }
01089                         node = ldns_rbtree_next(node);
01090                 }
01091         }
01092         return false;
01093 }

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