diff options
Diffstat (limited to 'ldns/dnssec_zone.h')
-rw-r--r-- | ldns/dnssec_zone.h | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/ldns/dnssec_zone.h b/ldns/dnssec_zone.h new file mode 100644 index 000000000000..4d2642fd1b45 --- /dev/null +++ b/ldns/dnssec_zone.h @@ -0,0 +1,476 @@ +/* + * special zone file structures and functions for better dnssec handling + * + * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal' + * dnssec_zone_rrsets, indexed by name and type + */ + +#ifndef LDNS_DNSSEC_ZONE_H +#define LDNS_DNSSEC_ZONE_H + +#include <ldns/ldns.h> +#include <ldns/rbtree.h> +#include <ldns/host2str.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Singly linked list of rrs + */ +typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs; +struct ldns_struct_dnssec_rrs +{ + ldns_rr *rr; + ldns_dnssec_rrs *next; +}; + +/** + * Singly linked list of RRsets + */ +typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets; +struct ldns_struct_dnssec_rrsets +{ + ldns_dnssec_rrs *rrs; + ldns_rr_type type; + ldns_dnssec_rrs *signatures; + ldns_dnssec_rrsets *next; +}; + +/** + * Structure containing all resource records for a domain name + * Including the derived NSEC3, if present + */ +typedef struct ldns_struct_dnssec_name ldns_dnssec_name; +struct ldns_struct_dnssec_name +{ + /** + * pointer to a dname containing the name. + * Usually points to the owner name of the first RR of the first RRset + */ + ldns_rdf *name; + /** + * Usually, the name is a pointer to the owner name of the first rr for + * this name, but sometimes there is no actual data to point to, + * for instance in + * names representing empty nonterminals. If so, set alloced to true to + * indicate that this data must also be freed when the name is freed + */ + bool name_alloced; + /** + * The rrsets for this name + */ + ldns_dnssec_rrsets *rrsets; + /** + * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3) + */ + ldns_rr *nsec; + /** + * signatures for the NSEC record + */ + ldns_dnssec_rrs *nsec_signatures; + /** + * Unlike what the name is_glue suggests, this field is set to true by + * ldns_dnssec_zone_mark_glue() or ldns_dnssec_zone_mark_and_get_glue() + * when the name, this dnssec_name struct represents, is occluded. + * Names that contain other occluded rrsets and records with glue on + * the delegation point will NOT have this bool set to true. + * This field should NOT be read directly, but only via the + * ldns_dnssec_name_is_glue() function! + */ + bool is_glue; + /** + * pointer to store the hashed name (only used when in an NSEC3 zone + */ + ldns_rdf *hashed_name; +}; + +/** + * Structure containing a dnssec zone + */ +struct ldns_struct_dnssec_zone { + /** points to the name containing the SOA RR */ + ldns_dnssec_name *soa; + /** tree of ldns_dnssec_names */ + ldns_rbtree_t *names; +}; +typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone; + +/** + * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs + * \return the allocated data + */ +ldns_dnssec_rrs *ldns_dnssec_rrs_new(); + +/** + * Frees the list of rrs, but *not* the individual ldns_rr records + * contained in the list + * + * \param[in] rrs the data structure to free + */ +void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs); + +/** + * Frees the list of rrs, and the individual ldns_rr records + * contained in the list + * + * \param[in] rrs the data structure to free + */ +void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs); + +/** + * Adds an RR to the list of RRs. The list will remain ordered + * + * \param[in] rrs the list to add to + * \param[in] rr the RR to add + * \return LDNS_STATUS_OK on success + */ +ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr); + +/** + * Prints the given rrs to the file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] rrs the list of RRs to print + */ +void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs); + +/** + * Prints the given rrs to the file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] rrs the list of RRs to print + */ +void ldns_dnssec_rrs_print_fmt(FILE *out, + const ldns_output_format *fmt, ldns_dnssec_rrs *rrs); + +/** + * Creates a new list (entry) of RRsets + * \return the newly allocated structure + */ +ldns_dnssec_rrsets *ldns_dnssec_rrsets_new(); + +/** + * Frees the list of rrsets and their rrs, but *not* the ldns_rr + * records in the sets + * + * \param[in] rrsets the data structure to free + */ +void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets); + +/** + * Frees the list of rrsets and their rrs, and the ldns_rr + * records in the sets + * + * \param[in] rrsets the data structure to free + */ +void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets); + +/** + * Returns the rr type of the rrset (that is head of the given list) + * + * \param[in] rrsets the rrset to get the type of + * \return the rr type + */ +ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets); + +/** + * Sets the RR type of the rrset (that is head of the given list) + * + * \param[in] rrsets the rrset to set the type of + * \param[in] type the type to set + * \return LDNS_STATUS_OK on success + */ +ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, + ldns_rr_type type); + +/** + * Add an ldns_rr to the corresponding RRset in the given list of RRsets. + * If it is not present, add it as a new RRset with 1 record. + * + * \param[in] rrsets the list of rrsets to add the RR to + * \param[in] rr the rr to add to the list of rrsets + * \return LDNS_STATUS_OK on success + */ +ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr); + +/** + * Print the given list of rrsets to the fiven file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] rrsets the list of RRsets to print + * \param[in] follow if set to false, only print the first RRset + */ +void ldns_dnssec_rrsets_print(FILE *out, + ldns_dnssec_rrsets *rrsets, + bool follow); + +/** + * Print the given list of rrsets to the fiven file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] rrsets the list of RRsets to print + * \param[in] follow if set to false, only print the first RRset + */ +void ldns_dnssec_rrsets_print_fmt(FILE *out, + const ldns_output_format *fmt, + ldns_dnssec_rrsets *rrsets, + bool follow); + + +/** + * Create a new data structure for a dnssec name + * \return the allocated structure + */ +ldns_dnssec_name *ldns_dnssec_name_new(); + +/** + * Create a new data structure for a dnssec name for the given RR + * + * \param[in] rr the RR to derive properties from, and to add to the name + */ +ldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr); + +/** + * Frees the name structure and its rrs and rrsets. + * Individual ldns_rr records therein are not freed + * + * \param[in] name the structure to free + */ +void ldns_dnssec_name_free(ldns_dnssec_name *name); + +/** + * Frees the name structure and its rrs and rrsets. + * Individual ldns_rr records contained in the name are also freed + * + * \param[in] name the structure to free + */ +void ldns_dnssec_name_deep_free(ldns_dnssec_name *name); + +/** + * Returns the domain name of the given dnssec_name structure + * + * \param[in] name the dnssec name to get the domain name from + * \return the domain name + */ +ldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name); + + +/** + * Sets the domain name of the given dnssec_name structure + * + * \param[in] name the dnssec name to set the domain name of + * \param[in] dname the domain name to set it to. This data is *not* copied. + */ +void ldns_dnssec_name_set_name(ldns_dnssec_name *name, + ldns_rdf *dname); +/** + * Returns if dnssec_name structure is marked as glue. + * The ldns_dnssec_zone_mark_glue() function has to be called on a zone before + * using this function. + * Only names that have only glue rrsets will be marked. + * Names that have other occluded rrsets and names containing glue on the + * delegation point will NOT be marked! + * + * \param[in] name the dnssec name to get the domain name from + * \return true if the structure is marked as glue, false otherwise. + */ +bool ldns_dnssec_name_is_glue(ldns_dnssec_name *name); + +/** + * Sets the NSEC(3) RR of the given dnssec_name structure + * + * \param[in] name the dnssec name to set the domain name of + * \param[in] nsec the nsec rr to set it to. This data is *not* copied. + */ +void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec); + +/** + * Compares the domain names of the two arguments in their + * canonical ordening. + * + * \param[in] a The first dnssec_name to compare + * \param[in] b The second dnssec_name to compare + * \return -1 if the domain name of a comes before that of b in canonical + * ordening, 1 if it is the other way around, and 0 if they are + * equal + */ +int ldns_dnssec_name_cmp(const void *a, const void *b); + +/** + * Inserts the given rr at the right place in the current dnssec_name + * No checking is done whether the name matches + * + * \param[in] name The ldns_dnssec_name to add the RR to + * \param[in] rr The RR to add + * \return LDNS_STATUS_OK on success, error code otherwise + */ +ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, + ldns_rr *rr); + +/** + * Find the RRset with the given type in within this name structure + * + * \param[in] name the name to find the RRset in + * \param[in] type the type of the RRset to find + * \return the RRset, or NULL if not present + */ +ldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, + ldns_rr_type type); + +/** + * Find the RRset with the given name and type in the zone + * + * \param[in] zone the zone structure to find the RRset in + * \param[in] dname the domain name of the RRset to find + * \param[in] type the type of the RRset to find + * \return the RRset, or NULL if not present + */ +ldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, + ldns_rdf *dname, + ldns_rr_type type); + +/** + * Prints the RRs in the dnssec name structure to the given + * file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] name the name structure to print the contents of + */ +void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name); + +/** + * Prints the RRs in the dnssec name structure to the given + * file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] name the name structure to print the contents of + */ +void ldns_dnssec_name_print_fmt(FILE *out, + const ldns_output_format *fmt, ldns_dnssec_name *name); + +/** + * Creates a new dnssec_zone structure + * \return the allocated structure + */ +ldns_dnssec_zone *ldns_dnssec_zone_new(); + +/** + * Create a new dnssec zone from a file. + * \param[out] z the new zone + * \param[in] *fp the filepointer to use + * \param[in] *origin the zones' origin + * \param[in] c default class to use (IN) + * \param[in] ttl default ttl to use + * + * \return ldns_status mesg with an error or LDNS_STATUS_OK + */ +ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, + ldns_rdf* origin, uint32_t ttl, ldns_rr_class c); + +/** + * Create a new dnssec zone from a file, keep track of the line numbering + * \param[out] z the new zone + * \param[in] *fp the filepointer to use + * \param[in] *origin the zones' origin + * \param[in] ttl default ttl to use + * \param[in] c default class to use (IN) + * \param[out] line_nr used for error msg, to get to the line number + * + * \return ldns_status mesg with an error or LDNS_STATUS_OK + */ +ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, + ldns_rdf* origin, uint32_t ttl, ldns_rr_class c, int* line_nr); + +/** + * Frees the given zone structure, and its rbtree of dnssec_names + * Individual ldns_rr RRs within those names are *not* freed + * \param[in] *zone the zone to free + */ +void ldns_dnssec_zone_free(ldns_dnssec_zone *zone); + +/** + * Frees the given zone structure, and its rbtree of dnssec_names + * Individual ldns_rr RRs within those names are also freed + * \param[in] *zone the zone to free + */ +void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone); + +/** + * Adds the given RR to the zone. + * It find whether there is a dnssec_name with that name present. + * If so, add it to that, if not create a new one. + * Special handling of NSEC and RRSIG provided + * + * \param[in] zone the zone to add the RR to + * \param[in] rr The RR to add + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, + ldns_rr *rr); + +/** + * Prints the rbtree of ldns_dnssec_name structures to the file descriptor + * + * \param[in] out the file descriptor to print the names to + * \param[in] tree the tree of ldns_dnssec_name structures to print + * \param[in] print_soa if true, print SOA records, if false, skip them + */ +void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa); + +/** + * Prints the rbtree of ldns_dnssec_name structures to the file descriptor + * + * \param[in] out the file descriptor to print the names to + * \param[in] fmt the format of the textual representation + * \param[in] tree the tree of ldns_dnssec_name structures to print + * \param[in] print_soa if true, print SOA records, if false, skip them + */ +void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_rbtree_t *tree, bool print_soa); + +/** + * Prints the complete zone to the given file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] zone the dnssec_zone to print + */ +void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone); + +/** + * Prints the complete zone to the given file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] zone the dnssec_zone to print + */ +void ldns_dnssec_zone_print_fmt(FILE *out, + const ldns_output_format *fmt, ldns_dnssec_zone *zone); + +/** + * Adds explicit dnssec_name structures for the empty nonterminals + * in this zone. (this is needed for NSEC3 generation) + * + * \param[in] zone the zone to check for empty nonterminals + * return LDNS_STATUS_OK on success. + */ +ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone); + +/** + * If a NSEC3PARAM is available in the apex, walks the zone and returns true + * on the first optout nsec3. + * + * \param[in] zone the zone to check for nsec3 optout records + * return true when the zone has at least one nsec3 optout record. + */ +bool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone); + +#ifdef __cplusplus +} +#endif + +#endif |