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); }
/** perf test a packet */ static void perftestpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out, const char* hex) { struct query_info qi; struct reply_info* rep = 0; int ret; uint16_t id; uint16_t flags; uint32_t timenow = 0; struct regional* region = regional_create(); struct edns_data edns; hex_to_buf(pkt, hex); memmove(&id, ldns_buffer_begin(pkt), sizeof(id)); if(ldns_buffer_limit(pkt) < 2) flags = 0; else memmove(&flags, ldns_buffer_at(pkt, 2), sizeof(flags)); flags = ntohs(flags); ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); if(ret != 0) { if(vbmp) printf("parse code %d: %s\n", ret, ldns_lookup_by_id(ldns_rcodes, ret)->name); if(ret == LDNS_RCODE_FORMERR) checkformerr(pkt); unit_assert(ret != LDNS_RCODE_SERVFAIL); } else { perf_encode(&qi, rep, id, flags, out, timenow, &edns); } query_info_clear(&qi); reply_info_parsedelete(rep, alloc); regional_destroy(region); }
ldns_rr * ldns_axfr_next(ldns_resolver *resolver) { ldns_rr *cur_rr; uint8_t *packet_wire; size_t packet_wire_size; ldns_lookup_table *rcode; ldns_status status; /* check if start() has been called */ if (!resolver || resolver->_socket == 0) { return NULL; } if (resolver->_cur_axfr_pkt) { if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; return ldns_axfr_next(resolver); } cur_rr = ldns_rr_clone(ldns_rr_list_rr( ldns_pkt_answer(resolver->_cur_axfr_pkt), resolver->_axfr_i)); resolver->_axfr_i++; if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { resolver->_axfr_soa_count++; if (resolver->_axfr_soa_count >= 2) { close(resolver->_socket); resolver->_socket = 0; ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; } } return cur_rr; } else { packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); if(!packet_wire) return NULL; status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, packet_wire_size); free(packet_wire); resolver->_axfr_i = 0; if (status != LDNS_STATUS_OK) { /* TODO: make status return type of this function (...api change) */ fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); fprintf(stderr, "Error in AXFR: %s\n", rcode->name); return NULL; } else { return ldns_axfr_next(resolver); } } }
/** nice string for rcode */ static void pretty_rcode(char* s, size_t len, int r) { ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes, r); if(rcode) { snprintf(s, len, "%s", rcode->name); } else { snprintf(s, len, "RCODE%d", r); } }
const char * ldns_get_errorstr_by_id(ldns_status err) { ldns_lookup_table *lt; lt = ldns_lookup_by_id(ldns_error_str, err); if (lt) { return lt->name; } return NULL; }
void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s) { char buf[256]; ldns_lookup_table *t = ldns_lookup_by_id(ldns_algorithms, alg); if(t&&t->name) snprintf(buf, sizeof(buf), "%s with algorithm %s", s, t->name); else snprintf(buf, sizeof(buf), "%s with algorithm ALG%u", s, (unsigned)alg); *reason = regional_strdup(env->scratch, buf); if(!*reason) *reason = s; }
/** 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); } }
/** entry to reply info conversion */ static void entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, struct regional* region, ldns_buffer* pkt, struct query_info* qi, struct reply_info** rep) { int ret; struct edns_data edns; entry_to_buf(e, pkt); /* lock alloc lock to please lock checking software. * alloc_special_obtain assumes it is talking to a ub-alloc, * and does not need to perform locking. Here the alloc is * the only one, so we lock it here */ lock_quick_lock(&alloc->lock); ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns); lock_quick_unlock(&alloc->lock); if(ret != 0) { printf("parse code %d: %s\n", ret, ldns_lookup_by_id(ldns_rcodes, ret)->name); unit_assert(ret != 0); } }
/** 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; }
/** test a packet */ static void testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out, const char* hex) { struct query_info qi; struct reply_info* rep = 0; int ret; uint16_t id; uint16_t flags; uint32_t timenow = 0; struct regional* region = regional_create(); struct edns_data edns; hex_to_buf(pkt, hex); memmove(&id, ldns_buffer_begin(pkt), sizeof(id)); if(ldns_buffer_limit(pkt) < 2) flags = 0; else memmove(&flags, ldns_buffer_at(pkt, 2), sizeof(flags)); flags = ntohs(flags); ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); if(ret != 0) { if(vbmp) printf("parse code %d: %s\n", ret, ldns_lookup_by_id(ldns_rcodes, ret)->name); if(ret == LDNS_RCODE_FORMERR) { unit_assert(!check_formerr_gone); checkformerr(pkt); } unit_assert(ret != LDNS_RCODE_SERVFAIL); } else if(!check_formerr_gone) { const size_t lim = 512; ret = reply_info_encode(&qi, rep, id, flags, out, timenow, region, 65535, (int)(edns.bits & EDNS_DO) ); unit_assert(ret != 0); /* udp packets should fit */ attach_edns_record(out, &edns); if(vbmp) printf("inlen %u outlen %u\n", (unsigned)ldns_buffer_limit(pkt), (unsigned)ldns_buffer_limit(out)); test_buffers(pkt, out); if(check_rrsigs) check_the_rrsigs(&qi, rep); if(ldns_buffer_limit(out) > lim) { ret = reply_info_encode(&qi, rep, id, flags, out, timenow, region, lim - calc_edns_field_size(&edns), (int)(edns.bits & EDNS_DO)); unit_assert(ret != 0); /* should fit, but with TC */ attach_edns_record(out, &edns); if( LDNS_QDCOUNT(ldns_buffer_begin(out)) != LDNS_QDCOUNT(ldns_buffer_begin(pkt)) || LDNS_ANCOUNT(ldns_buffer_begin(out)) != LDNS_ANCOUNT(ldns_buffer_begin(pkt)) || LDNS_NSCOUNT(ldns_buffer_begin(out)) != LDNS_NSCOUNT(ldns_buffer_begin(pkt))) unit_assert( LDNS_TC_WIRE(ldns_buffer_begin(out))); /* must set TC bit if shortened */ unit_assert(ldns_buffer_limit(out) <= lim); } } query_info_clear(&qi); reply_info_parsedelete(rep, alloc); regional_destroy(region); }
ldns_rr * ldns_axfr_next(ldns_resolver *resolver) { ldns_rr *cur_rr; uint8_t *packet_wire; size_t packet_wire_size; ldns_lookup_table *rcode; ldns_status status; /* check if start() has been called */ if (!resolver || resolver->_socket == 0) { return NULL; } if (resolver->_cur_axfr_pkt) { if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; return ldns_axfr_next(resolver); } cur_rr = ldns_rr_clone(ldns_rr_list_rr( ldns_pkt_answer(resolver->_cur_axfr_pkt), resolver->_axfr_i)); resolver->_axfr_i++; if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { resolver->_axfr_soa_count++; if (resolver->_axfr_soa_count >= 2) { #ifndef USE_WINSOCK close(resolver->_socket); #else closesocket(resolver->_socket); #endif resolver->_socket = 0; ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; } } return cur_rr; } else { packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); if(!packet_wire) return NULL; status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, packet_wire_size); free(packet_wire); resolver->_axfr_i = 0; if (status != LDNS_STATUS_OK) { /* TODO: make status return type of this function (...api change) */ fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); /* RoRi: we must now also close the socket, otherwise subsequent uses of the same resolver structure will fail because the link is still open or in an undefined state */ #ifndef USE_WINSOCK close(resolver->_socket); #else closesocket(resolver->_socket); #endif resolver->_socket = 0; return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); fprintf(stderr, "Error in AXFR: %s\n", rcode->name); /* RoRi: we must now also close the socket, otherwise subsequent uses of the same resolver structure will fail because the link is still open or in an undefined state */ #ifndef USE_WINSOCK close(resolver->_socket); #else closesocket(resolver->_socket); #endif resolver->_socket = 0; return NULL; } else { return ldns_axfr_next(resolver); } } }