void log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, uint16_t type, uint16_t dclass) { char buf[LDNS_MAX_DOMAINLEN+1]; char t[12], c[12]; const char *ts, *cs; if(verbosity < v) return; dname_str(name, buf); if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; else if(ldns_rr_descript(type) && ldns_rr_descript(type)->_name) ts = ldns_rr_descript(type)->_name; else { snprintf(t, sizeof(t), "TYPE%d", (int)type); ts = t; } if(ldns_lookup_by_id(ldns_rr_classes, (int)dclass) && ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name) cs = ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name; else { snprintf(c, sizeof(c), "CLASS%d", (int)dclass); cs = c; } log_info("%s %s %s %s", str, buf, ts, cs); }
/** return true if type needs domain name compression in rdata */ static const ldns_rr_descriptor* type_rdata_compressable(struct ub_packed_rrset_key* key) { uint16_t t = ntohs(key->rk.type); if(ldns_rr_descript(t) && ldns_rr_descript(t)->_compress == LDNS_RR_COMPRESS) return ldns_rr_descript(t); return 0; }
/** analyze rr in packet */ static void analyze_rr(ldns_buffer* pkt, int q) { uint16_t type, dclass, len; uint32_t ttl; analyze_dname(pkt); type = ldns_buffer_read_u16(pkt); dclass = ldns_buffer_read_u16(pkt); printf("type %s(%d)", ldns_rr_descript(type)? ldns_rr_descript(type)->_name: "??" , (int)type); printf(" class %s(%d) ", ldns_lookup_by_id(ldns_rr_classes, (int)dclass)?ldns_lookup_by_id( ldns_rr_classes, (int)dclass)->name:"??", (int)dclass); if(q) { printf("\n"); } else { ttl = ldns_buffer_read_u32(pkt); printf(" ttl %d (0x%x)", (int)ttl, (unsigned)ttl); len = ldns_buffer_read_u16(pkt); printf(" rdata len %d:\n", (int)len); if(ldns_rr_descript(type)) analyze_rdata(pkt, ldns_rr_descript(type), len); else ldns_buffer_skip(pkt, (ssize_t)len); } }
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); }
/** print extended stats */ static int print_ext(SSL* ssl, struct stats_info* s) { int i; char nm[16]; const ldns_rr_descriptor* desc; const ldns_lookup_table* lt; /* TYPE */ for(i=0; i<STATS_QTYPE_NUM; i++) { if(inhibit_zero && s->svr.qtype[i] == 0) continue; desc = ldns_rr_descript((uint16_t)i); if(desc && desc->_name) { snprintf(nm, sizeof(nm), "%s", desc->_name); } else if (i == LDNS_RR_TYPE_IXFR) { snprintf(nm, sizeof(nm), "IXFR"); } else if (i == LDNS_RR_TYPE_AXFR) { snprintf(nm, sizeof(nm), "AXFR"); } else if (i == LDNS_RR_TYPE_MAILA) { snprintf(nm, sizeof(nm), "MAILA"); } else if (i == LDNS_RR_TYPE_MAILB) { snprintf(nm, sizeof(nm), "MAILB"); } else if (i == LDNS_RR_TYPE_ANY) { snprintf(nm, sizeof(nm), "ANY"); } else { snprintf(nm, sizeof(nm), "TYPE%d", i); } if(!ssl_printf(ssl, "num.query.type.%s"SQ"%u\n", nm, (unsigned)s->svr.qtype[i])) return 0; } if(!inhibit_zero || s->svr.qtype_big) { if(!ssl_printf(ssl, "num.query.type.other"SQ"%u\n", (unsigned)s->svr.qtype_big)) return 0; } /* CLASS */ for(i=0; i<STATS_QCLASS_NUM; i++) { if(inhibit_zero && s->svr.qclass[i] == 0) continue; lt = ldns_lookup_by_id(ldns_rr_classes, i); if(lt && lt->name) { snprintf(nm, sizeof(nm), "%s", lt->name); } else { snprintf(nm, sizeof(nm), "CLASS%d", i); } if(!ssl_printf(ssl, "num.query.class.%s"SQ"%u\n", nm, (unsigned)s->svr.qclass[i])) return 0; } if(!inhibit_zero || s->svr.qclass_big) { if(!ssl_printf(ssl, "num.query.class.other"SQ"%u\n", (unsigned)s->svr.qclass_big)) return 0; } /* OPCODE */ for(i=0; i<STATS_OPCODE_NUM; i++) { if(inhibit_zero && s->svr.qopcode[i] == 0) continue; lt = ldns_lookup_by_id(ldns_opcodes, i); if(lt && lt->name) { snprintf(nm, sizeof(nm), "%s", lt->name); } else { snprintf(nm, sizeof(nm), "OPCODE%d", i); } if(!ssl_printf(ssl, "num.query.opcode.%s"SQ"%u\n", nm, (unsigned)s->svr.qopcode[i])) return 0; } /* transport */ if(!ssl_printf(ssl, "num.query.tcp"SQ"%u\n", (unsigned)s->svr.qtcp)) return 0; if(!ssl_printf(ssl, "num.query.ipv6"SQ"%u\n", (unsigned)s->svr.qipv6)) return 0; /* flags */ if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%u\n", (unsigned)s->svr.qbit_QR)) return 0; if(!ssl_printf(ssl, "num.query.flags.AA"SQ"%u\n", (unsigned)s->svr.qbit_AA)) return 0; if(!ssl_printf(ssl, "num.query.flags.TC"SQ"%u\n", (unsigned)s->svr.qbit_TC)) return 0; if(!ssl_printf(ssl, "num.query.flags.RD"SQ"%u\n", (unsigned)s->svr.qbit_RD)) return 0; if(!ssl_printf(ssl, "num.query.flags.RA"SQ"%u\n", (unsigned)s->svr.qbit_RA)) return 0; if(!ssl_printf(ssl, "num.query.flags.Z"SQ"%u\n", (unsigned)s->svr.qbit_Z)) return 0; if(!ssl_printf(ssl, "num.query.flags.AD"SQ"%u\n", (unsigned)s->svr.qbit_AD)) return 0; if(!ssl_printf(ssl, "num.query.flags.CD"SQ"%u\n", (unsigned)s->svr.qbit_CD)) return 0; if(!ssl_printf(ssl, "num.query.edns.present"SQ"%u\n", (unsigned)s->svr.qEDNS)) return 0; if(!ssl_printf(ssl, "num.query.edns.DO"SQ"%u\n", (unsigned)s->svr.qEDNS_DO)) return 0; /* RCODE */ for(i=0; i<STATS_RCODE_NUM; i++) { if(inhibit_zero && s->svr.ans_rcode[i] == 0) continue; lt = ldns_lookup_by_id(ldns_rcodes, i); if(lt && lt->name) { snprintf(nm, sizeof(nm), "%s", lt->name); } else { snprintf(nm, sizeof(nm), "RCODE%d", i); } if(!ssl_printf(ssl, "num.answer.rcode.%s"SQ"%u\n", nm, (unsigned)s->svr.ans_rcode[i])) return 0; } if(!inhibit_zero || s->svr.ans_rcode_nodata) { if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%u\n", (unsigned)s->svr.ans_rcode_nodata)) return 0; } /* validation */ if(!ssl_printf(ssl, "num.answer.secure"SQ"%u\n", (unsigned)s->svr.ans_secure)) return 0; if(!ssl_printf(ssl, "num.answer.bogus"SQ"%u\n", (unsigned)s->svr.ans_bogus)) return 0; if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%u\n", (unsigned)s->svr.rrset_bogus)) return 0; /* threat detection */ if(!ssl_printf(ssl, "unwanted.queries"SQ"%u\n", (unsigned)s->svr.unwanted_queries)) return 0; if(!ssl_printf(ssl, "unwanted.replies"SQ"%u\n", (unsigned)s->svr.unwanted_replies)) return 0; return 1; }
ldns_status do_chase(ldns_resolver *res, ldns_rdf *name, ldns_rr_type type, ldns_rr_class c, ldns_rr_list *trusted_keys, ldns_pkt *pkt_o, uint16_t qflags, ldns_rr_list *prev_key_list, int verbosity) { ldns_rr_list *rrset = NULL; ldns_status result; ldns_rr *orig_rr = NULL; /* ldns_rr_list *sigs; ldns_rr *cur_sig; uint16_t sig_i; ldns_rr_list *keys; */ ldns_pkt *pkt; ldns_status tree_result; ldns_dnssec_data_chain *chain; ldns_dnssec_trust_tree *tree; const ldns_rr_descriptor *descriptor; descriptor = ldns_rr_descript(type); ldns_dname2canonical(name); pkt = ldns_pkt_clone(pkt_o); if (!name) { ldns_pkt_free(pkt); return LDNS_STATUS_EMPTY_LABEL; } if (verbosity != -1) { printf(";; Chasing: "); ldns_rdf_print(stdout, name); if (descriptor && descriptor->_name) { printf(" %s\n", descriptor->_name); } else { printf(" type %d\n", type); } } if (!trusted_keys || ldns_rr_list_rr_count(trusted_keys) < 1) { } if (pkt) { rrset = ldns_pkt_rr_list_by_name_and_type(pkt, name, type, LDNS_SECTION_ANSWER ); if (!rrset) { /* nothing in answer, try authority */ rrset = ldns_pkt_rr_list_by_name_and_type(pkt, name, type, LDNS_SECTION_AUTHORITY ); } /* answer might be a cname, chase that first, then chase cname target? (TODO) */ if (!rrset) { rrset = ldns_pkt_rr_list_by_name_and_type(pkt, name, LDNS_RR_TYPE_CNAME, LDNS_SECTION_ANSWER ); if (!rrset) { /* nothing in answer, try authority */ rrset = ldns_pkt_rr_list_by_name_and_type(pkt, name, LDNS_RR_TYPE_CNAME, LDNS_SECTION_AUTHORITY ); } } } else { /* no packet? */ if (verbosity >= 0) { fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR)); fprintf(stderr, "\n"); } return LDNS_STATUS_MEM_ERR; } if (!rrset) { /* not found in original packet, try again */ ldns_pkt_free(pkt); pkt = NULL; pkt = ldns_resolver_query(res, name, type, c, qflags); if (!pkt) { if (verbosity >= 0) { fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_NETWORK_ERR)); fprintf(stderr, "\n"); } return LDNS_STATUS_NETWORK_ERR; } if (verbosity >= 5) { ldns_pkt_print(stdout, pkt); } rrset = ldns_pkt_rr_list_by_name_and_type(pkt, name, type, LDNS_SECTION_ANSWER ); } orig_rr = ldns_rr_new(); /* if the answer had no answer section, we need to construct our own rr (for instance if * the rr qe asked for doesn't exist. This rr will be destroyed when the chain is freed */ if (ldns_pkt_ancount(pkt) < 1) { ldns_rr_set_type(orig_rr, type); ldns_rr_set_owner(orig_rr, ldns_rdf_clone(name)); chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, ldns_rr_clone(orig_rr)); } else { /* chase the first answer */ chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, NULL); } if (verbosity >= 4) { printf("\n\nDNSSEC Data Chain:\n"); ldns_dnssec_data_chain_print(stdout, chain); } result = LDNS_STATUS_OK; tree = ldns_dnssec_derive_trust_tree(chain, NULL); if (verbosity >= 2) { printf("\n\nDNSSEC Trust tree:\n"); ldns_dnssec_trust_tree_print(stdout, tree, 0, true); } if (ldns_rr_list_rr_count(trusted_keys) > 0) { tree_result = ldns_dnssec_trust_tree_contains_keys(tree, trusted_keys); if (tree_result == LDNS_STATUS_DNSSEC_EXISTENCE_DENIED) { if (verbosity >= 1) { printf("Existence denied or verifiably insecure\n"); } result = LDNS_STATUS_OK; } else if (tree_result != LDNS_STATUS_OK) { if (verbosity >= 1) { printf("No trusted keys found in tree: first error was: %s\n", ldns_get_errorstr_by_id(tree_result)); } result = tree_result; } } else { result = -1; if (verbosity >= 0) { printf("You have not provided any trusted keys.\n"); } } ldns_rr_free(orig_rr); ldns_dnssec_trust_tree_free(tree); ldns_dnssec_data_chain_deep_free(chain); ldns_rr_list_deep_free(rrset); ldns_pkt_free(pkt); /* ldns_rr_free(orig_rr);*/ return result; }
/*return hash name match*/ ldns_rr * ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) { uint8_t algorithm; uint32_t iterations; uint8_t salt_length; uint8_t *salt; ldns_rdf *sname, *hashed_sname; size_t nsec_i; ldns_rr *nsec; ldns_rr *result = NULL; ldns_status status; const ldns_rr_descriptor *descriptor; ldns_rdf *zone_name; if (verbosity >= 4) { printf(";; finding exact match for "); descriptor = ldns_rr_descript(qtype); if (descriptor && descriptor->_name) { printf("%s ", descriptor->_name); } else { printf("TYPE%d ", qtype); } ldns_rdf_print(stdout, qname); printf("\n"); } if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { if (verbosity >= 4) { printf("no qname, nsec3s or list empty\n"); } return NULL; } nsec = ldns_rr_list_rr(nsec3s, 0); algorithm = ldns_nsec3_algorithm(nsec); salt_length = ldns_nsec3_salt_length(nsec); salt = ldns_nsec3_salt_data(nsec); iterations = ldns_nsec3_iterations(nsec); sname = ldns_rdf_clone(qname); if (verbosity >= 4) { printf(";; owner name hashes to: "); } hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); status = ldns_dname_cat(hashed_sname, zone_name); if (verbosity >= 4) { ldns_rdf_print(stdout, hashed_sname); printf("\n"); } for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { nsec = ldns_rr_list_rr(nsec3s, nsec_i); /* check values of iterations etc! */ /* exact match? */ if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { result = nsec; goto done; } } done: ldns_rdf_deep_free(zone_name); ldns_rdf_deep_free(sname); ldns_rdf_deep_free(hashed_sname); LDNS_FREE(salt); if (verbosity >= 4) { if (result) { printf(";; Found.\n"); } else { printf(";; Not foud.\n"); } } return result; }
/** * Compare two RRs in the same RRset and determine their relative * canonical order. * @param rrset: the rrset in which to perform compares. * @param i: first RR to compare * @param j: first RR to compare * @return 0 if RR i== RR j, -1 if <, +1 if >. */ static int canonical_compare(struct ub_packed_rrset_key* rrset, size_t i, size_t j) { struct packed_rrset_data* d = (struct packed_rrset_data*) rrset->entry.data; const ldns_rr_descriptor* desc; uint16_t type = ntohs(rrset->rk.type); size_t minlen; int c; if(i==j) return 0; /* in case rdata-len is to be compared for canonical order c = memcmp(d->rr_data[i], d->rr_data[j], 2); if(c != 0) return c; */ switch(type) { /* These RR types have only a name as RDATA. * This name has to be canonicalized.*/ case LDNS_RR_TYPE_NS: case LDNS_RR_TYPE_MD: case LDNS_RR_TYPE_MF: case LDNS_RR_TYPE_CNAME: case LDNS_RR_TYPE_MB: case LDNS_RR_TYPE_MG: case LDNS_RR_TYPE_MR: case LDNS_RR_TYPE_PTR: case LDNS_RR_TYPE_DNAME: return query_dname_compare(d->rr_data[i]+2, d->rr_data[j]+2); /* These RR types have STR and fixed size rdata fields * before one or more name fields that need canonicalizing, * and after that a byte-for byte remainder can be compared. */ /* type starts with the name; remainder is binary compared */ case LDNS_RR_TYPE_NXT: /* use rdata field formats */ case LDNS_RR_TYPE_MINFO: case LDNS_RR_TYPE_RP: case LDNS_RR_TYPE_SOA: case LDNS_RR_TYPE_RT: case LDNS_RR_TYPE_AFSDB: case LDNS_RR_TYPE_KX: case LDNS_RR_TYPE_MX: case LDNS_RR_TYPE_SIG: /* RRSIG signer name has to be downcased */ case LDNS_RR_TYPE_RRSIG: case LDNS_RR_TYPE_PX: case LDNS_RR_TYPE_NAPTR: case LDNS_RR_TYPE_SRV: desc = ldns_rr_descript(type); log_assert(desc); /* this holds for the types that need canonicalizing */ log_assert(desc->_minimum == desc->_maximum); return canonical_compare_byfield(d, desc, i, j); case LDNS_RR_TYPE_HINFO: /* no longer downcased */ case LDNS_RR_TYPE_NSEC: default: /* For unknown RR types, or types not listed above, * no canonicalization is needed, do binary compare */ /* byte for byte compare, equal means shortest first*/ minlen = d->rr_len[i]-2; if(minlen > d->rr_len[j]-2) minlen = d->rr_len[j]-2; c = memcmp(d->rr_data[i]+2, d->rr_data[j]+2, minlen); if(c!=0) return c; /* rdata equal, shortest is first */ if(d->rr_len[i] < d->rr_len[j]) return -1; if(d->rr_len[i] > d->rr_len[j]) return 1; /* rdata equal, length equal */ break; } return 0; }
/** do the rdata copy */ static int rdata_copy(ldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, struct rr_parse* rr, uint32_t* rr_ttl, uint16_t type) { uint16_t pkt_len; const ldns_rr_descriptor* desc; *rr_ttl = ldns_read_uint32(rr->ttl_data); /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ if(*rr_ttl & 0x80000000U) *rr_ttl = 0; if(*rr_ttl < MIN_TTL) *rr_ttl = MIN_TTL; if(*rr_ttl < data->ttl) data->ttl = *rr_ttl; if(rr->outside_packet) { /* uncompressed already, only needs copy */ memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size); return 1; } ldns_buffer_set_position(pkt, (size_t) (rr->ttl_data - ldns_buffer_begin(pkt) + sizeof(uint32_t))); /* insert decompressed size into rdata len stored in memory */ /* -2 because rdatalen bytes are not included. */ pkt_len = htons(rr->size - 2); memmove(to, &pkt_len, sizeof(uint16_t)); to += 2; /* read packet rdata len */ pkt_len = ldns_buffer_read_u16(pkt); if(ldns_buffer_remaining(pkt) < pkt_len) return 0; desc = ldns_rr_descript(type); if(pkt_len > 0 && desc && desc->_dname_count > 0) { int count = (int)desc->_dname_count; int rdf = 0; size_t len; size_t oldpos; /* decompress dnames. */ while(pkt_len > 0 && count) { switch(desc->_wireformat[rdf]) { case LDNS_RDF_TYPE_DNAME: oldpos = ldns_buffer_position(pkt); dname_pkt_copy(pkt, to, ldns_buffer_current(pkt)); to += pkt_dname_len(pkt); pkt_len -= ldns_buffer_position(pkt)-oldpos; count--; len = 0; break; case LDNS_RDF_TYPE_STR: len = ldns_buffer_current(pkt)[0] + 1; break; default: len = get_rdf_size(desc->_wireformat[rdf]); break; } if(len) { memmove(to, ldns_buffer_current(pkt), len); to += len; ldns_buffer_skip(pkt, (ssize_t)len); log_assert(len <= pkt_len); pkt_len -= len; } rdf++; } } /* copy remaining rdata */ if(pkt_len > 0) memmove(to, ldns_buffer_current(pkt), pkt_len); return 1; }