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                         status = LDNS_STATUS_OK;
00712                         break;
00713 
00714                 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
00715                         status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
00716                         break;
00717 
00718                 default:
00719                         goto error;
00720                 }
00721         }
00722 
00723         if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
00724                 (void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
00725                 for (i = 0; status == LDNS_STATUS_OK && 
00726                                 i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
00727                         cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
00728                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
00729                 }
00730                 for (i = 0; status == LDNS_STATUS_OK &&
00731                                 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
00732                                 i++){
00733                         cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
00734                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
00735                 }
00736         } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
00737                 for (i = 0; status == LDNS_STATUS_OK &&
00738                                 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
00739                                 i++){
00740                         cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
00741                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
00742                 }
00743         }
00744 
00745         if (z) {
00746                 *z = newzone;
00747                 newzone = NULL;
00748         } else {
00749                 ldns_dnssec_zone_free(newzone);
00750         }
00751 
00752 error:
00753 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
00754         if (zone) {
00755                 ldns_zone_free(zone);
00756         }
00757 #endif
00758         ldns_rr_list_free(todo_nsec3_rrsigs);
00759         ldns_rr_list_free(todo_nsec3s);
00760 
00761         if (my_origin) {
00762                 ldns_rdf_deep_free(my_origin);
00763         }
00764         if (my_prev) {
00765                 ldns_rdf_deep_free(my_prev);
00766         }
00767         if (newzone) {
00768                 ldns_dnssec_zone_free(newzone);
00769         }
00770         return status;
00771 }
00772 
00773 ldns_status
00774 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
00775                 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
00776 {
00777         return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
00778 }
00779 
00780 void
00781 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
00782         (void) arg;
00783         ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
00784         LDNS_FREE(node);
00785 }
00786 
00787 void
00788 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
00789         (void) arg;
00790         ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
00791         LDNS_FREE(node);
00792 }
00793 
00794 void
00795 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
00796 {
00797         if (zone) {
00798                 if (zone->names) {
00799                         /* destroy all name structures within the tree */
00800                         ldns_traverse_postorder(zone->names,
00801                                                     ldns_dnssec_name_node_free,
00802                                                     NULL);
00803                         LDNS_FREE(zone->names);
00804                 }
00805                 LDNS_FREE(zone);
00806         }
00807 }
00808 
00809 void
00810 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
00811 {
00812         if (zone) {
00813                 if (zone->names) {
00814                         /* destroy all name structures within the tree */
00815                         ldns_traverse_postorder(zone->names,
00816                                                     ldns_dnssec_name_node_deep_free,
00817                                                     NULL);
00818                         LDNS_FREE(zone->names);
00819                 }
00820                 LDNS_FREE(zone);
00821         }
00822 }
00823 
00824 /* use for dname comparison in tree */
00825 int
00826 ldns_dname_compare_v(const void *a, const void *b) {
00827         return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
00828 }
00829 
00830 ldns_rbnode_t *
00831 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
00832                                      ldns_rr *rr) {
00833         ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
00834         ldns_dnssec_name *current_name;
00835         ldns_rdf *hashed_name;
00836 
00837         hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
00838 
00839         while (current_node != LDNS_RBTREE_NULL) {
00840                 current_name = (ldns_dnssec_name *) current_node->data;
00841                 if (!current_name->hashed_name) {
00842                         current_name->hashed_name =
00843                                 ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
00844                 }
00845                 if (ldns_dname_compare(hashed_name,
00846                                                    current_name->hashed_name)
00847                     == 0) {
00848                         ldns_rdf_deep_free(hashed_name);
00849                         return current_node;
00850                 }
00851                 current_node = ldns_rbtree_next(current_node);
00852         }
00853         ldns_rdf_deep_free(hashed_name);
00854         return NULL;
00855 }
00856 
00857 ldns_status
00858 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
00859 {
00860         ldns_status result = LDNS_STATUS_OK;
00861         ldns_dnssec_name *cur_name;
00862         ldns_rbnode_t *cur_node;
00863         ldns_rr_type type_covered = 0;
00864 
00865         if (!zone || !rr) {
00866                 return LDNS_STATUS_ERR;
00867         }
00868 
00869         if (!zone->names) {
00870                 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
00871                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
00872         }
00873 
00874         /* we need the original of the hashed name if this is
00875            an NSEC3, or an RRSIG that covers an NSEC3 */
00876         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
00877                 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
00878         }
00879         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
00880             type_covered == LDNS_RR_TYPE_NSEC3) {
00881                 cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
00882                                                                                            rr);
00883                 if (!cur_node) {
00884                         return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
00885                 }
00886         } else {
00887                 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
00888         }
00889 
00890         if (!cur_node) {
00891                 /* add */
00892                 cur_name = ldns_dnssec_name_new_frm_rr(rr);
00893                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
00894                 cur_node = LDNS_MALLOC(ldns_rbnode_t);
00895                 if(!cur_node) {
00896                         ldns_dnssec_name_free(cur_name);
00897                         return LDNS_STATUS_MEM_ERR;
00898                 }
00899                 cur_node->key = ldns_rr_owner(rr);
00900                 cur_node->data = cur_name;
00901                 (void)ldns_rbtree_insert(zone->names, cur_node);
00902         } else {
00903                 cur_name = (ldns_dnssec_name *) cur_node->data;
00904                 result = ldns_dnssec_name_add_rr(cur_name, rr);
00905         }
00906 
00907         if (result != LDNS_STATUS_OK) {
00908                 fprintf(stderr, "error adding rr: ");
00909                 ldns_rr_print(stderr, rr);
00910         }
00911 
00912         /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
00913         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
00914                 zone->soa = cur_name;
00915         }
00916 
00917         return result;
00918 }
00919 
00920 void
00921 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
00922                 ldns_rbtree_t *tree, 
00923                 bool print_soa)
00924 {
00925         ldns_rbnode_t *node;
00926         ldns_dnssec_name *name;
00927 
00928         node = ldns_rbtree_first(tree);
00929         while (node != LDNS_RBTREE_NULL) {
00930                 name = (ldns_dnssec_name *) node->data;
00931                 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
00932                 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00933                         fprintf(out, ";\n");
00934                 node = ldns_rbtree_next(node);
00935         }
00936 }
00937 
00938 void
00939 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
00940 {
00941         ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
00942                        tree, print_soa);
00943 }
00944 
00945 void
00946 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
00947                ldns_dnssec_zone *zone)
00948 {
00949         if (zone) {
00950                 if (zone->soa) {
00951                         if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
00952                                 fprintf(out, ";; Zone: ");
00953                                 ldns_rdf_print(out, ldns_dnssec_name_name(
00954                                                         zone->soa));
00955                                 fprintf(out, "\n;\n");
00956                         }
00957                         ldns_dnssec_rrsets_print_fmt(out, fmt,
00958                                         ldns_dnssec_name_find_rrset(
00959                                                 zone->soa, 
00960                                                 LDNS_RR_TYPE_SOA), 
00961                                         false);
00962                         if ((fmt->flags & LDNS_COMMENT_LAYOUT))
00963                                 fprintf(out, ";\n");
00964                 }
00965 
00966                 if (zone->names) {
00967                         ldns_dnssec_zone_names_print_fmt(out, fmt, 
00968                                         zone->names, false);
00969                 }
00970         }
00971 }
00972 
00973 void
00974 ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
00975 {
00976         ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
00977 }
00978 
00979 ldns_status
00980 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
00981 {
00982         ldns_dnssec_name *new_name;
00983         ldns_rdf *cur_name;
00984         ldns_rdf *next_name;
00985         ldns_rbnode_t *cur_node, *next_node, *new_node;
00986 
00987         /* for the detection */
00988         uint16_t i, cur_label_count, next_label_count;
00989         uint16_t soa_label_count = 0;
00990         ldns_rdf *l1, *l2;
00991         int lpos;
00992 
00993         if (!zone) {
00994                 return LDNS_STATUS_ERR;
00995         }
00996         if (zone->soa && zone->soa->name) {
00997                 soa_label_count = ldns_dname_label_count(zone->soa->name);
00998         }
00999         
01000         cur_node = ldns_rbtree_first(zone->names);
01001         while (cur_node != LDNS_RBTREE_NULL) {
01002                 next_node = ldns_rbtree_next(cur_node);
01003                 
01004                 /* skip glue */
01005                 while (next_node != LDNS_RBTREE_NULL && 
01006                        next_node->data &&
01007                        ((ldns_dnssec_name *)next_node->data)->is_glue
01008                 ) {
01009                         next_node = ldns_rbtree_next(next_node);
01010                 }
01011 
01012                 if (next_node == LDNS_RBTREE_NULL) {
01013                         next_node = ldns_rbtree_first(zone->names);
01014                 }
01015                 if (! cur_node->data || ! next_node->data) {
01016                         return LDNS_STATUS_ERR;
01017                 }
01018                 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
01019                 next_name = ((ldns_dnssec_name *)next_node->data)->name;
01020                 cur_label_count = ldns_dname_label_count(cur_name);
01021                 next_label_count = ldns_dname_label_count(next_name);
01022 
01023                 /* Since the names are in canonical order, we can
01024                  * recognize empty non-terminals by their labels;
01025                  * every label after the first one on the next owner
01026                  * name is a non-terminal if it either does not exist
01027                  * in the current name or is different from the same
01028                  * label in the current name (counting from the end)
01029                  */
01030                 for (i = 1; i < next_label_count - soa_label_count; i++) {
01031                         lpos = (int)cur_label_count - (int)next_label_count + (int)i;
01032                         if (lpos >= 0) {
01033                                 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
01034                         } else {
01035                                 l1 = NULL;
01036                         }
01037                         l2 = ldns_dname_clone_from(next_name, i);
01038 
01039                         if (!l1 || ldns_dname_compare(l1, l2) != 0) {
01040                                 /* We have an empty nonterminal, add it to the
01041                                  * tree
01042                                  */
01043                                 new_name = ldns_dnssec_name_new();
01044                                 if (!new_name) {
01045                                         return LDNS_STATUS_MEM_ERR;
01046                                 }
01047                                 new_name->name = ldns_dname_clone_from(next_name,
01048                                                                        i);
01049                                 if (!new_name->name) {
01050                                         ldns_dnssec_name_free(new_name);
01051                                         return LDNS_STATUS_MEM_ERR;
01052                                 }
01053                                 new_name->name_alloced = true;
01054                                 new_node = LDNS_MALLOC(ldns_rbnode_t);
01055                                 if (!new_node) {
01056                                         ldns_dnssec_name_free(new_name);
01057                                         return LDNS_STATUS_MEM_ERR;
01058                                 }
01059                                 new_node->key = new_name->name;
01060                                 new_node->data = new_name;
01061                                 (void)ldns_rbtree_insert(zone->names, new_node);
01062                         }
01063                         ldns_rdf_deep_free(l1);
01064                         ldns_rdf_deep_free(l2);
01065                 }
01066                 
01067                 /* we might have inserted a new node after
01068                  * the current one so we can't just use next()
01069                  */
01070                 if (next_node != ldns_rbtree_first(zone->names)) {
01071                         cur_node = next_node;
01072                 } else {
01073                         cur_node = LDNS_RBTREE_NULL;
01074                 }
01075         }
01076         return LDNS_STATUS_OK;
01077 }
01078 
01079 bool
01080 ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
01081 {
01082         ldns_rr* nsec3;
01083         ldns_rbnode_t* node;
01084 
01085         if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
01086                 node = ldns_rbtree_first(zone->names);
01087                 while (node != LDNS_RBTREE_NULL) {
01088                         nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
01089                         if (nsec3 &&ldns_rr_get_type(nsec3) 
01090                                         == LDNS_RR_TYPE_NSEC3 &&
01091                                         ldns_nsec3_optout(nsec3)) {
01092                                 return true;
01093                         }
01094                         node = ldns_rbtree_next(node);
01095                 }
01096         }
01097         return false;
01098 }

Generated on Wed Dec 19 16:56:42 2012 for ldns by  doxygen 1.4.7