ldns_rr_list* loadKeyfile(const char *filename) { FILE *key_file; ldns_status status; ldns_rr_list *trusted_keys; ldns_zone *trusted_zone; // Try open trusted key file key_file = fopen(filename, "r"); if (!key_file) { if (mp_verbose >= 1) fprintf(stderr,"Error opening trusted-key file %s: %s\n", filename, strerror(errno)); return NULL; } ldns_rdf *origin = ldns_dname_new_frm_str("."); // Read key file status = ldns_zone_new_frm_fp(&trusted_zone, key_file, origin, 900, LDNS_RR_CLASS_IN); ldns_rdf_deep_free(origin); fclose(key_file); if (status == LDNS_STATUS_OK) { trusted_keys = ldns_rr_list_clone(ldns_zone_rrs(trusted_zone)); ldns_zone_deep_free(trusted_zone); } else { if (mp_verbose >= 1) fprintf(stderr,"loading keyfile failed."); return NULL; } return trusted_keys; }
ldns_zone * ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt) { ldns_dnssec_zone *dnssec_zone; ldns_zone *signed_zone; ldns_rr_list *new_rrs; size_t i; signed_zone = ldns_zone_new(); dnssec_zone = ldns_dnssec_zone_new(); (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone)); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_rr_list_rr(ldns_zone_rrs(zone), i)); ldns_zone_push_rr(signed_zone, ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), i))); } new_rrs = ldns_rr_list_new(); (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone, new_rrs, key_list, ldns_dnssec_default_replace_signatures, NULL, algorithm, flags, iterations, salt_length, salt); for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); } ldns_rr_list_deep_free(new_rrs); ldns_dnssec_zone_free(dnssec_zone); return signed_zone; }
void ldns_zone_sort(ldns_zone *zone) { ldns_rr_list *zrr; assert(zone != NULL); zrr = ldns_zone_rrs(zone); ldns_rr_list_sort(zrr); }
/* * Read a hints file as root * * The file with the given path should contain a list of NS RRs * for the root zone and A records for those NS RRs. * Read them, check them, and append the a records to the rr list given. */ ldns_rr_list * read_root_hints(const char *filename) { FILE *fp = NULL; int line_nr = 0; ldns_zone *z; ldns_status status; ldns_rr_list *addresses = NULL; ldns_rr *rr; size_t i; fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "Unable to open %s for reading: %s\n", filename, strerror(errno)); return NULL; } status = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, 0, &line_nr); fclose(fp); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error reading root hints file: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } else { addresses = ldns_rr_list_new(); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { rr = ldns_rr_list_rr(ldns_zone_rrs(z), i); /*if ((address_family == 0 || address_family == 1) && */ if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ) { ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr)); } /*if ((address_family == 0 || address_family == 2) &&*/ if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) { ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr)); } } ldns_zone_deep_free(z); return addresses; } }
ldns_zone * ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) { ldns_dnssec_zone *dnssec_zone; ldns_zone *signed_zone; ldns_rr_list *new_rrs; size_t i; signed_zone = ldns_zone_new(); dnssec_zone = ldns_dnssec_zone_new(); (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone)); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_rr_list_rr(ldns_zone_rrs(zone), i)); ldns_zone_push_rr(signed_zone, ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), i))); } new_rrs = ldns_rr_list_new(); (void) ldns_dnssec_zone_sign(dnssec_zone, new_rrs, key_list, ldns_dnssec_default_replace_signatures, NULL); for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); } ldns_rr_list_deep_free(new_rrs); ldns_dnssec_zone_free(dnssec_zone); return signed_zone; }
static int udp_bind(int sock, int port, const char *my_address) { struct sockaddr_in addr; in_addr_t maddr = INADDR_ANY; if (my_address) { #ifdef AF_INET6 if (inet_pton(AF_INET6, my_address, &maddr) < 1) { #else if (0) { #endif if (inet_pton(AF_INET, my_address, &maddr) < 1) { return -2; } } } #ifndef S_SPLINT_S addr.sin_family = AF_INET; #endif addr.sin_port = (in_port_t) htons((uint16_t)port); addr.sin_addr.s_addr = maddr; return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr)); } /* this will probably be moved to a better place in the library itself */ ldns_rr_list * get_rrset(const ldns_zone *zone, const ldns_rdf *owner_name, const ldns_rr_type qtype, const ldns_rr_class qclass) { uint16_t i; ldns_rr_list *rrlist = ldns_rr_list_new(); ldns_rr *cur_rr; if (!zone || !owner_name) { fprintf(stderr, "Warning: get_rrset called with NULL zone or owner name\n"); return rrlist; } for (i = 0; i < ldns_zone_rr_count(zone); i++) { cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i); if (ldns_dname_compare(ldns_rr_owner(cur_rr), owner_name) == 0 && ldns_rr_get_class(cur_rr) == qclass && ldns_rr_get_type(cur_rr) == qtype ) { ldns_rr_list_push_rr(rrlist, ldns_rr_clone(cur_rr)); } } printf("Found rrset of %u rrs\n", (unsigned int) ldns_rr_list_rr_count(rrlist)); return rrlist; }
int main(int argc, char **argv) { char *filename; FILE *fp; ldns_zone *z; int line_nr = 0; int c; bool canonicalize = false; bool sort = false; bool strip = false; bool only_dnssec = false; bool print_soa = true; ldns_status s; size_t i; ldns_rr_list *stripped_list; ldns_rr *cur_rr; ldns_rr_type cur_rr_type; while ((c = getopt(argc, argv, "cdhnsvz")) != -1) { switch(c) { case 'c': canonicalize = true; break; case 'd': only_dnssec = true; if (strip) { fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n"); } break; case 'h': printf("Usage: %s [-c] [-v] [-z] <zonefile>\n", argv[0]); printf("\tReads the zonefile and prints it.\n"); printf("\tThe RR count of the zone is printed to stderr.\n"); printf("\t-c canonicalize all rrs in the zone.\n"); printf("\t-d only show DNSSEC data from the zone\n"); printf("\t-h show this text\n"); printf("\t-n do not print the SOA record\n"); printf("\t-s strip DNSSEC data from the zone\n"); printf("\t-v shows the version and exits\n"); printf("\t-z sort the zone (implies -c).\n"); printf("\nif no file is given standard input is read\n"); exit(EXIT_SUCCESS); break; case 'n': print_soa = false; break; case 's': strip = true; if (only_dnssec) { fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n"); } break; case 'v': printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); exit(EXIT_SUCCESS); break; case 'z': canonicalize = true; sort = true; break; } } argc -= optind; argv += optind; if (argc == 0) { fp = stdin; } else { filename = argv[0]; fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); exit(EXIT_FAILURE); } } s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr); if (strip) { stripped_list = ldns_rr_list_new(); while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) { cur_rr_type = ldns_rr_get_type(cur_rr); if (cur_rr_type == LDNS_RR_TYPE_RRSIG || cur_rr_type == LDNS_RR_TYPE_NSEC || cur_rr_type == LDNS_RR_TYPE_NSEC3 || cur_rr_type == LDNS_RR_TYPE_NSEC3PARAMS ) { ldns_rr_free(cur_rr); } else { ldns_rr_list_push_rr(stripped_list, cur_rr); } } ldns_rr_list_free(ldns_zone_rrs(z)); ldns_zone_set_rrs(z, stripped_list); } if (only_dnssec) { stripped_list = ldns_rr_list_new(); while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) { cur_rr_type = ldns_rr_get_type(cur_rr); if (cur_rr_type == LDNS_RR_TYPE_RRSIG || cur_rr_type == LDNS_RR_TYPE_NSEC || cur_rr_type == LDNS_RR_TYPE_NSEC3 || cur_rr_type == LDNS_RR_TYPE_NSEC3PARAMS ) { ldns_rr_list_push_rr(stripped_list, cur_rr); } else { ldns_rr_free(cur_rr); } } ldns_rr_list_free(ldns_zone_rrs(z)); ldns_zone_set_rrs(z, stripped_list); } if (s == LDNS_STATUS_OK) { if (canonicalize) { ldns_rr2canonical(ldns_zone_soa(z)); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i)); } } if (sort) { ldns_zone_sort(z); } if (print_soa && ldns_zone_soa(z)) { ldns_rr_print(stdout, ldns_zone_soa(z)); } ldns_rr_list_print(stdout, ldns_zone_rrs(z)); ldns_zone_deep_free(z); } else { fprintf(stderr, "%s at %d\n", ldns_get_errorstr_by_id(s), line_nr); exit(EXIT_FAILURE); } fclose(fp); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { char *filename; FILE *fp; ldns_zone *z; int line_nr = 0; int c; bool canonicalize = false; bool sort = false; bool strip = false; bool only_dnssec = false; bool print_soa = true; ldns_status s; size_t i; ldns_rr_list *stripped_list; ldns_rr *cur_rr; ldns_rr_type cur_rr_type; ldns_output_format_storage fmt_storage; ldns_output_format* fmt = ldns_output_format_init(&fmt_storage); ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL; int soa_serial_increment_func_data = 0; while ((c = getopt(argc, argv, "0bcdhnpsu:U:vzS:")) != -1) { switch(c) { case 'b': fmt->flags |= ( LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS ); break; case '0': fmt->flags |= LDNS_FMT_ZEROIZE_RRSIGS; break; case 'c': canonicalize = true; break; case 'd': only_dnssec = true; if (strip) { fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n"); } break; case 'h': print_usage("ldns-read-zone"); break; case 'n': print_soa = false; break; case 'p': fmt->flags |= LDNS_FMT_PAD_SOA_SERIAL; break; case 's': strip = true; if (only_dnssec) { fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n"); } break; case 'u': s = ldns_output_format_set_type(fmt, ldns_get_rr_type_by_name(optarg)); if (s != LDNS_STATUS_OK) { fprintf( stderr , "Cannot set rr type %s " "in output format to " "print as unknown type: %s\n" , ldns_rr_descript( ldns_get_rr_type_by_name(optarg) )->_name , ldns_get_errorstr_by_id(s) ); exit(EXIT_FAILURE); } break; case 'U': s = ldns_output_format_clear_type(fmt, ldns_get_rr_type_by_name(optarg)); if (s != LDNS_STATUS_OK) { fprintf( stderr , "Cannot set rr type %s " "in output format to not " "print as unknown type: %s\n" , ldns_rr_descript( ldns_get_rr_type_by_name(optarg) )->_name , ldns_get_errorstr_by_id(s) ); exit(EXIT_FAILURE); } break; case 'v': printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); exit(EXIT_SUCCESS); break; case 'z': canonicalize = true; sort = true; break; case 'S': strip = true; if (*optarg == '+' || *optarg == '-') { soa_serial_increment_func_data = atoi(optarg); soa_serial_increment_func = ldns_soa_serial_increment_by; } else if (! strtok(optarg, "0123456789")) { soa_serial_increment_func_data = atoi(optarg); soa_serial_increment_func = ldns_soa_serial_identity; } else if (!strcasecmp(optarg, "YYYYMMDDxx")){ soa_serial_increment_func = ldns_soa_serial_datecounter; } else if (!strcasecmp(optarg, "unixtime")){ soa_serial_increment_func = ldns_soa_serial_unixtime; } else { fprintf(stderr, "-S expects a number " "optionally preceded by a " "+ or - sign to indicate an " "offset, or the text YYYYMM" "DDxx or unixtime\n"); exit(EXIT_FAILURE); } break; } } argc -= optind; argv += optind; if (argc == 0) { fp = stdin; } else { filename = argv[0]; fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); exit(EXIT_FAILURE); } } s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr); fclose(fp); if (s != LDNS_STATUS_OK) { fprintf(stderr, "%s at %d\n", ldns_get_errorstr_by_id(s), line_nr); exit(EXIT_FAILURE); } if (strip) { stripped_list = ldns_rr_list_new(); while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) { cur_rr_type = ldns_rr_get_type(cur_rr); if (cur_rr_type == LDNS_RR_TYPE_RRSIG || cur_rr_type == LDNS_RR_TYPE_NSEC || cur_rr_type == LDNS_RR_TYPE_NSEC3 || cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM ) { ldns_rr_free(cur_rr); } else { ldns_rr_list_push_rr(stripped_list, cur_rr); } } ldns_rr_list_free(ldns_zone_rrs(z)); ldns_zone_set_rrs(z, stripped_list); } if (only_dnssec) { stripped_list = ldns_rr_list_new(); while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) { cur_rr_type = ldns_rr_get_type(cur_rr); if (cur_rr_type == LDNS_RR_TYPE_RRSIG || cur_rr_type == LDNS_RR_TYPE_NSEC || cur_rr_type == LDNS_RR_TYPE_NSEC3 || cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM ) { ldns_rr_list_push_rr(stripped_list, cur_rr); } else { ldns_rr_free(cur_rr); } } ldns_rr_list_free(ldns_zone_rrs(z)); ldns_zone_set_rrs(z, stripped_list); } if (canonicalize) { ldns_rr2canonical(ldns_zone_soa(z)); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i)); } } if (sort) { ldns_zone_sort(z); } if (print_soa && ldns_zone_soa(z)) { if (soa_serial_increment_func) { ldns_rr_soa_increment_func_int( ldns_zone_soa(z) , soa_serial_increment_func , soa_serial_increment_func_data ); } ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z)); } ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z)); ldns_zone_deep_free(z); exit(EXIT_SUCCESS); }
ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr) { ldns_rr* cur_rr; size_t i; ldns_rdf *my_origin = NULL; ldns_rdf *my_prev = NULL; ldns_dnssec_zone *newzone = ldns_dnssec_zone_new(); /* when reading NSEC3s, there is a chance that we encounter nsecs for empty nonterminals, whose nonterminals we cannot derive yet because the needed information is to be read later. in that case we keep a list of those nsec3's and retry to add them later */ ldns_rr_list* todo_nsec3s = ldns_rr_list_new(); ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new(); ldns_status status = LDNS_STATUS_MEM_ERR; #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP ldns_zone* zone = NULL; if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr) != LDNS_STATUS_OK) goto error; #else uint32_t my_ttl = ttl; #endif if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error; if (origin) { if (!(my_origin = ldns_rdf_clone(origin))) goto error; if (!(my_prev = ldns_rdf_clone(origin))) goto error; } #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone)) != LDNS_STATUS_OK) goto error; for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i); status = LDNS_STATUS_OK; #else while (!feof(fp)) { status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin, &my_prev, line_nr); #endif switch (status) { case LDNS_STATUS_OK: status = ldns_dnssec_zone_add_rr(newzone, cur_rr); if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) { if (rr_is_rrsig_covering(cur_rr, LDNS_RR_TYPE_NSEC3)){ ldns_rr_list_push_rr(todo_nsec3_rrsigs, cur_rr); } else { ldns_rr_list_push_rr(todo_nsec3s, cur_rr); } status = LDNS_STATUS_OK; } else if (status != LDNS_STATUS_OK) goto error; break; case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ status = LDNS_STATUS_OK; break; case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */ status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; break; default: goto error; } } if (ldns_rr_list_rr_count(todo_nsec3s) > 0) { (void) ldns_dnssec_zone_add_empty_nonterminals(newzone); for (i = 0; status == LDNS_STATUS_OK && i < ldns_rr_list_rr_count(todo_nsec3s); i++) { cur_rr = ldns_rr_list_rr(todo_nsec3s, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } } if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) { for (i = 0; status == LDNS_STATUS_OK && i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } } if (z) { *z = newzone; newzone = NULL; } else { ldns_dnssec_zone_free(newzone); } error: #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP if (zone) { ldns_zone_free(zone); } #endif ldns_rr_list_free(todo_nsec3_rrsigs); ldns_rr_list_free(todo_nsec3s); if (my_origin) { ldns_rdf_deep_free(my_origin); } if (my_prev) { ldns_rdf_deep_free(my_prev); } if (newzone) { ldns_dnssec_zone_free(newzone); } return status; } ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, uint32_t ttl, ldns_rr_class ATTR_UNUSED(c)) { return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); } static void ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) { (void) arg; ldns_dnssec_name_free((ldns_dnssec_name *)node->data); LDNS_FREE(node); }
bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr) { return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr); }
bool ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list) { return ldns_rr_list_cat(ldns_zone_rrs(z), list); }
/* * Get the list of glue records in a zone */ ldns_rr_list * ldns_zone_glue_rr_list(const ldns_zone *z) { /* when do we find glue? It means we find an IP address * (AAAA/A) for a nameserver listed in the zone * * Alg used here: * first find all the zonecuts (NS records) * find all the AAAA or A records (can be done it the * above loop). * * Check if the aaaa/a list are subdomains under the * NS domains. If yes -> glue, if no -> not glue */ ldns_rr_list *zone_cuts; ldns_rr_list *addr; ldns_rr_list *glue; ldns_rr *r, *ns, *a; ldns_rdf *dname_a, *dname_ns, *ns_owner; uint16_t i,j; zone_cuts = ldns_rr_list_new(); addr = ldns_rr_list_new(); glue = ldns_rr_list_new(); for(i = 0; i < ldns_zone_rr_count(z); i++) { r = ldns_rr_list_rr(ldns_zone_rrs(z), i); if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A || ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) { /* possibly glue */ ldns_rr_list_push_rr(addr, r); continue; } if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) { /* multiple zones will end up here - * for now; not a problem */ /* don't add NS records for the current zone itself */ if (ldns_rdf_compare(ldns_rr_owner(r), ldns_rr_owner(ldns_zone_soa(z))) != 0) { ldns_rr_list_push_rr(zone_cuts, r); } continue; } } /* will sorting make it quicker ?? */ for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) { ns = ldns_rr_list_rr(zone_cuts, i); ns_owner = ldns_rr_owner(ns); dname_ns = ldns_rr_ns_nsdname(ns); for(j = 0; j < ldns_rr_list_rr_count(addr); j++) { a = ldns_rr_list_rr(addr, j); dname_a = ldns_rr_owner(a); /* if (ldns_dname_is_subdomain(dname_a, ns_owner) && ldns_rdf_compare(dname_ns, dname_a) == 0) { */ if (ldns_dname_is_subdomain(dname_a, ns_owner)) { /* GLUE! */ ldns_rr_list_push_rr(glue, a); } } } ldns_rr_list_free(addr); ldns_rr_list_free(zone_cuts); if (ldns_rr_list_rr_count(glue) == 0) { ldns_rr_list_free(glue); return NULL; } else { return glue; } }
int main(int argc, char **argv) { char *fn1, *fn2; FILE *fp1, *fp2; ldns_zone *z1, *z2; ldns_status s; size_t i , j; ldns_rr_list *rrl1, *rrl2; int rr_cmp, rr_chg = 0; ldns_rr *rr1 = NULL, *rr2 = NULL, *rrx = NULL; int line_nr1 = 0, line_nr2 = 0; size_t rrc1 , rrc2; size_t num_ins = 0, num_del = 0, num_chg = 0; int c; bool opt_deleted = false, opt_inserted = false, opt_changed = false; bool sort = true, inc_soa = false; char op = 0; while ((c = getopt(argc, argv, "ahvdicsz")) != -1) { switch (c) { case 'h': usage(argc, argv); exit(EXIT_SUCCESS); break; case 'v': printf("%s version %s (ldns version %s)\n", argv[0], LDNS_VERSION, ldns_version()); exit(EXIT_SUCCESS); break; case 's': inc_soa = true; break; case 'z': sort = false; break; case 'd': opt_deleted = true; break; case 'i': opt_inserted = true; break; case 'c': opt_changed = true; break; case 'a': opt_deleted = true; opt_inserted = true; opt_changed = true; break; } } argc -= optind; argv += optind; if (argc != 2) { argc -= optind; argv -= optind; usage(argc, argv); exit(EXIT_FAILURE); } fn1 = argv[0]; fp1 = fopen(fn1, "r"); if (!fp1) { fprintf(stderr, "Unable to open %s: %s\n", fn1, strerror(errno)); exit(EXIT_FAILURE); } /* Read first zone */ s = ldns_zone_new_frm_fp_l(&z1, fp1, NULL, 0, LDNS_RR_CLASS_IN, &line_nr1); if (s != LDNS_STATUS_OK) { fclose(fp1); fprintf(stderr, "%s: %s at %d\n", fn1, ldns_get_errorstr_by_id(s), line_nr1); exit(EXIT_FAILURE); } fclose(fp1); fn2 = argv[1]; fp2 = fopen(fn2, "r"); if (!fp2) { fprintf(stderr, "Unable to open %s: %s\n", fn2, strerror(errno)); exit(EXIT_FAILURE); } /* Read second zone */ s = ldns_zone_new_frm_fp_l(&z2, fp2, NULL, 0, LDNS_RR_CLASS_IN, &line_nr2); if (s != LDNS_STATUS_OK) { ldns_zone_deep_free(z1); fclose(fp2); fprintf(stderr, "%s: %s at %d\n", fn2, ldns_get_errorstr_by_id(s), line_nr2); exit(EXIT_FAILURE); } fclose(fp2); rrl1 = ldns_zone_rrs(z1); rrc1 = ldns_rr_list_rr_count(rrl1); rrl2 = ldns_zone_rrs(z2); rrc2 = ldns_rr_list_rr_count(rrl2); if (sort) { /* canonicalize zone 1 */ ldns_rr2canonical(ldns_zone_soa(z1)); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z1)); i++) { ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z1), i)); } /* sort zone 1 */ ldns_zone_sort(z1); /* canonicalize zone 2 */ ldns_rr2canonical(ldns_zone_soa(z2)); for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z2)); i++) { ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z2), i)); } /* sort zone 2 */ ldns_zone_sort(z2); } if(inc_soa) { ldns_rr_list* wsoa = ldns_rr_list_new(); ldns_rr_list_push_rr(wsoa, ldns_zone_soa(z1)); ldns_rr_list_cat(wsoa, rrl1); rrl1 = wsoa; rrc1 = ldns_rr_list_rr_count(rrl1); wsoa = ldns_rr_list_new(); ldns_rr_list_push_rr(wsoa, ldns_zone_soa(z2)); ldns_rr_list_cat(wsoa, rrl2); rrl2 = wsoa; rrc2 = ldns_rr_list_rr_count(rrl2); if(sort) { ldns_rr_list_sort(rrl1); ldns_rr_list_sort(rrl2); } } /* * Walk through both zones. The previously seen resource record is * kept (in the variable rrx) so that we can recognize when we are * handling a new owner name. If the owner name changes, we have to * set the operator again. */ for (i = 0, j = 0; i < rrc1 || j < rrc2;) { rr_cmp = 0; if (i < rrc1 && j < rrc2) { rr1 = ldns_rr_list_rr(rrl1, i); rr2 = ldns_rr_list_rr(rrl2, j); rr_cmp = ldns_rr_compare(rr1, rr2); /* Completely skip if the rrs are equal */ if (rr_cmp == 0) { i++; j++; continue; } rr_chg = ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)); } else if (i >= rrc1) { /* we have reached the end of zone 1, so the current record * from zone 2 automatically sorts higher */ rr1 = NULL; rr2 = ldns_rr_list_rr(rrl2, j); rr_chg = rr_cmp = 1; } else if (j >= rrc2) { /* we have reached the end of zone 2, so the current record * from zone 1 automatically sorts lower */ rr1 = ldns_rr_list_rr(rrl1, i); rr2 = NULL; rr_chg = rr_cmp = -1; } if (rr_cmp < 0) { i++; if ((rrx != NULL) && (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rrx) ) != 0)) { /* The owner name is different, forget previous rr */ rrx = NULL; } if (rrx == NULL) { if (rr_chg == 0) { num_chg++; op = OP_CHG; } else { num_del++; op = OP_DEL; } rrx = rr1; } if (((op == OP_DEL) && opt_deleted) || ((op == OP_CHG) && opt_changed)) { printf("%c-", op); ldns_rr_print(stdout, rr1); } } else if (rr_cmp > 0) { j++; if ((rrx != NULL) && (ldns_dname_compare(ldns_rr_owner(rr2), ldns_rr_owner(rrx) ) != 0)) { rrx = NULL; } if (rrx == NULL) { if (rr_chg == 0) { num_chg++; op = OP_CHG; } else { num_ins++; op = OP_INS; } /* remember this rr for it's name in the next iteration */ rrx = rr2; } if (((op == OP_INS) && opt_inserted) || ((op == OP_CHG) && opt_changed)) { printf("%c+", op); ldns_rr_print(stdout, rr2); } } } printf("\t%c%u\t%c%u\t%c%u\n", OP_INS, (unsigned int) num_ins, OP_DEL, (unsigned int) num_del, OP_CHG, (unsigned int) num_chg); /* Free resources */ if(inc_soa) { ldns_rr_list_free(rrl1); ldns_rr_list_free(rrl2); } ldns_zone_deep_free(z2); ldns_zone_deep_free(z1); return 0; }