/** perf test a packet */ static void perftestpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out, const char* hex) { struct query_info qi; struct reply_info* rep = 0; int ret; uint16_t id; uint16_t flags; time_t timenow = 0; struct regional* region = regional_create(); struct edns_data edns; hex_to_buf(pkt, hex); memmove(&id, sldns_buffer_begin(pkt), sizeof(id)); if(sldns_buffer_limit(pkt) < 2) flags = 0; else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags)); flags = ntohs(flags); ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); if(ret != 0) { char rbuf[16]; sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf)); if(vbmp) printf("parse code %d: %s\n", ret, rbuf); 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); }
/** nice string for rcode */ static void pretty_rcode(char* s, size_t len, int r) { char d[16]; sldns_wire2str_rcode_buf(r, d, sizeof(d)); snprintf(s, len, "%s", d); }
/** entry to reply info conversion */ static void entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, struct regional* region, sldns_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) { char rcode[16]; sldns_wire2str_rcode_buf(ret, rcode, sizeof(rcode)); printf("parse code %d: %s\n", ret, rcode); unit_assert(ret != 0); } }
/** show end stats */ static void perfendstats(struct perfinfo* info) { double dt, qps; struct timeval timeout, now; int i, lost; if(gettimeofday(&now, NULL) < 0) fatal_exit("gettimeofday: %s", strerror(errno)); timeout = now; perf_tv_subtract(&timeout, &info->since); stat_printout(info, &now, &timeout); timeout = now; perf_tv_subtract(&timeout, &info->start); dt = (double)(timeout.tv_sec*1000000 + timeout.tv_usec) / 1000000.0; qps = (double)(info->total_recv) / dt; lost = (int)(info->total_sent - info->total_recv) - (int)info->io_num; if(!info->quiet) { printf("overall time: %g sec\n", (double)timeout.tv_sec + (double)timeout.tv_usec/1000000.); if(lost > 0) printf("Packets lost: %d\n", (int)lost); for(i=0; i<(int)(sizeof(info->by_rcode)/sizeof(size_t)); i++) { if(info->by_rcode[i] > 0) { char rc[16]; sldns_wire2str_rcode_buf(i, rc, sizeof(rc)); printf("%d(%5s): %u replies\n", i, rc, (unsigned)info->by_rcode[i]); } } } printf("average qps: %g\n", qps); }
/** test a packet */ static void testpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_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, sldns_buffer_begin(pkt), sizeof(id)); if(sldns_buffer_limit(pkt) < 2) flags = 0; else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags)); flags = ntohs(flags); ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); if(ret != 0) { char rbuf[16]; sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf)); if(vbmp) printf("parse code %d: %s\n", ret, rbuf); 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)sldns_buffer_limit(pkt), (unsigned)sldns_buffer_limit(out)); if(!check_nosameness) test_buffers(pkt, out); if(check_rrsigs) check_the_rrsigs(&qi, rep); if(sldns_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(sldns_buffer_begin(out)) != LDNS_QDCOUNT(sldns_buffer_begin(pkt)) || LDNS_ANCOUNT(sldns_buffer_begin(out)) != LDNS_ANCOUNT(sldns_buffer_begin(pkt)) || LDNS_NSCOUNT(sldns_buffer_begin(out)) != LDNS_NSCOUNT(sldns_buffer_begin(pkt))) unit_assert( LDNS_TC_WIRE(sldns_buffer_begin(out))); /* must set TC bit if shortened */ unit_assert(sldns_buffer_limit(out) <= lim); } } query_info_clear(&qi); reply_info_parsedelete(rep, alloc); regional_destroy(region); }
/** print extended */ static void print_extended(struct ub_stats_info* s) { int i; char nm[16]; /* TYPE */ for(i=0; i<UB_STATS_QTYPE_NUM; i++) { if(inhibit_zero && s->svr.qtype[i] == 0) continue; sldns_wire2str_type_buf((uint16_t)i, nm, sizeof(nm)); PR_UL_SUB("num.query.type", nm, s->svr.qtype[i]); } if(!inhibit_zero || s->svr.qtype_big) { PR_UL("num.query.type.other", s->svr.qtype_big); } /* CLASS */ for(i=0; i<UB_STATS_QCLASS_NUM; i++) { if(inhibit_zero && s->svr.qclass[i] == 0) continue; sldns_wire2str_class_buf((uint16_t)i, nm, sizeof(nm)); PR_UL_SUB("num.query.class", nm, s->svr.qclass[i]); } if(!inhibit_zero || s->svr.qclass_big) { PR_UL("num.query.class.other", s->svr.qclass_big); } /* OPCODE */ for(i=0; i<UB_STATS_OPCODE_NUM; i++) { if(inhibit_zero && s->svr.qopcode[i] == 0) continue; sldns_wire2str_opcode_buf(i, nm, sizeof(nm)); PR_UL_SUB("num.query.opcode", nm, s->svr.qopcode[i]); } /* transport */ PR_UL("num.query.tcp", s->svr.qtcp); PR_UL("num.query.tcpout", s->svr.qtcp_outgoing); PR_UL("num.query.tls", s->svr.qtls); PR_UL("num.query.ipv6", s->svr.qipv6); /* flags */ PR_UL("num.query.flags.QR", s->svr.qbit_QR); PR_UL("num.query.flags.AA", s->svr.qbit_AA); PR_UL("num.query.flags.TC", s->svr.qbit_TC); PR_UL("num.query.flags.RD", s->svr.qbit_RD); PR_UL("num.query.flags.RA", s->svr.qbit_RA); PR_UL("num.query.flags.Z", s->svr.qbit_Z); PR_UL("num.query.flags.AD", s->svr.qbit_AD); PR_UL("num.query.flags.CD", s->svr.qbit_CD); PR_UL("num.query.edns.present", s->svr.qEDNS); PR_UL("num.query.edns.DO", s->svr.qEDNS_DO); /* RCODE */ for(i=0; i<UB_STATS_RCODE_NUM; i++) { /* Always include RCODEs 0-5 */ if(inhibit_zero && i > LDNS_RCODE_REFUSED && s->svr.ans_rcode[i] == 0) continue; sldns_wire2str_rcode_buf(i, nm, sizeof(nm)); PR_UL_SUB("num.answer.rcode", nm, s->svr.ans_rcode[i]); } if(!inhibit_zero || s->svr.ans_rcode_nodata) { PR_UL("num.answer.rcode.nodata", s->svr.ans_rcode_nodata); } /* iteration */ PR_UL("num.query.ratelimited", s->svr.queries_ratelimited); /* validation */ PR_UL("num.answer.secure", s->svr.ans_secure); PR_UL("num.answer.bogus", s->svr.ans_bogus); PR_UL("num.rrset.bogus", s->svr.rrset_bogus); PR_UL("num.query.aggressive.NOERROR", s->svr.num_neg_cache_noerror); PR_UL("num.query.aggressive.NXDOMAIN", s->svr.num_neg_cache_nxdomain); /* threat detection */ PR_UL("unwanted.queries", s->svr.unwanted_queries); PR_UL("unwanted.replies", s->svr.unwanted_replies); /* cache counts */ PR_UL("msg.cache.count", s->svr.msg_cache_count); PR_UL("rrset.cache.count", s->svr.rrset_cache_count); PR_UL("infra.cache.count", s->svr.infra_cache_count); PR_UL("key.cache.count", s->svr.key_cache_count); #ifdef USE_DNSCRYPT PR_UL("dnscrypt_shared_secret.cache.count", s->svr.shared_secret_cache_count); PR_UL("num.query.dnscrypt.shared_secret.cachemiss", s->svr.num_query_dnscrypt_secret_missed_cache); PR_UL("dnscrypt_nonce.cache.count", s->svr.nonce_cache_count); PR_UL("num.query.dnscrypt.replay", s->svr.num_query_dnscrypt_replay); #endif /* USE_DNSCRYPT */ PR_UL("num.query.authzone.up", s->svr.num_query_authzone_up); PR_UL("num.query.authzone.down", s->svr.num_query_authzone_down); #ifdef CLIENT_SUBNET PR_UL("num.query.subnet", s->svr.num_query_subnet); PR_UL("num.query.subnet_cache", s->svr.num_query_subnet_cache); #endif }