/** 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); }
int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc, struct query_info* qinf, struct reply_info** rep, struct regional* region, struct edns_data* edns) { /* use scratch pad region-allocator during parsing. */ struct msg_parse* msg; int ret; qinf->qname = NULL; *rep = NULL; if(!(msg = regional_alloc(region, sizeof(*msg)))) { return LDNS_RCODE_SERVFAIL; } memset(msg, 0, sizeof(*msg)); sldns_buffer_set_position(pkt, 0); if((ret = parse_packet(pkt, msg, region)) != 0) { return ret; } if((ret = parse_extract_edns(msg, edns)) != 0) return ret; /* parse OK, allocate return structures */ /* this also performs dname decompression */ if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) { query_info_clear(qinf); reply_info_parsedelete(*rep, alloc); *rep = NULL; return LDNS_RCODE_SERVFAIL; } return 0; }
/** verify and test an entry - every rr in the message */ static void verifytest_entry(struct entry* e, struct alloc_cache* alloc, struct regional* region, ldns_buffer* pkt, struct ub_packed_rrset_key* dnskey, struct module_env* env, struct val_env* ve) { struct query_info qinfo; struct reply_info* rep = NULL; size_t i; regional_free_all(region); if(vsig) { printf("verifying pkt:\n"); ldns_pkt_print(stdout, e->reply_list->reply); printf("\n"); } entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); for(i=0; i<rep->rrset_count; i++) { verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo); } reply_info_parsedelete(rep, alloc); query_info_clear(&qinfo); }
void query_entry_delete(void *k, void* ATTR_UNUSED(arg)) { struct msgreply_entry* q = (struct msgreply_entry*)k; lock_rw_destroy(&q->entry.lock); query_info_clear(&q->key); free(q); }
/** Test hash algo - NSEC3 hash it and compare result */ static void nsec3_hash_test_entry(struct entry* e, rbtree_type* ct, struct alloc_cache* alloc, struct regional* region, sldns_buffer* buf) { struct query_info qinfo; struct reply_info* rep = NULL; struct ub_packed_rrset_key* answer, *nsec3; struct nsec3_cached_hash* hash = NULL; int ret; uint8_t* qname; if(vsig) { char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, e->reply_list->reply_len); printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory"); free(s); } entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep); nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3); answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA); qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len); /* check test is OK */ unit_assert(nsec3 && answer && qname); ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname, qinfo.qname_len, &hash); if(ret != 1) { printf("Bad nsec3_hash_name retcode %d\n", ret); unit_assert(ret == 1); } unit_assert(hash->dname && hash->hash && hash->hash_len && hash->b32 && hash->b32_len); unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]); /* does not do lowercasing. */ unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len) == 0); reply_info_parsedelete(rep, alloc); query_info_clear(&qinfo); }
/** DS sig test an entry - get DNSKEY and DS in entry and verify */ static void dstest_entry(struct entry* e, struct alloc_cache* alloc, struct regional* region, sldns_buffer* pkt, struct module_env* env) { struct query_info qinfo; struct reply_info* rep = NULL; struct ub_packed_rrset_key* ds, *dnskey; int ret; regional_free_all(region); if(vsig) { char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt, e->reply_list->reply_len); printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory"); free(s); } entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); ds = find_rrset_type(rep, LDNS_RR_TYPE_DS); dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY); /* check test is OK */ unit_assert(ds && dnskey); ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0); if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) { if(vsig) { printf("result(yes)= %s\n", ret?"yes":"no"); } unit_assert(ret); } else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) { if(vsig) { printf("result(no)= %s\n", ret?"yes":"no"); } unit_assert(!ret); verbose(VERB_QUERY, "DS fail: OK; matched unit test"); } else { fatal_exit("Bad qname in DS unit test, yes or no"); } reply_info_parsedelete(rep, alloc); query_info_clear(&qinfo); }
/** extract DNSKEY rrset from answer and convert it */ static struct ub_packed_rrset_key* extract_keys(struct entry* e, struct alloc_cache* alloc, struct regional* region, ldns_buffer* pkt) { struct ub_packed_rrset_key* dnskey = NULL; struct query_info qinfo; struct reply_info* rep = NULL; size_t i; entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); for(i=0; i<rep->an_numrrsets; i++) { if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) { dnskey = rep->rrsets[i]; rep->rrsets[i] = NULL; break; } } unit_assert(dnskey); reply_info_parsedelete(rep, alloc); query_info_clear(&qinfo); return dnskey; }
/** 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); }
static int log_top (FILE * fp, char *filename) { char *linebuf = NULL; T_QUERY_INFO query_info_buf[MAX_SRV_HANDLE]; char client_msg_buf[CLIENT_MSG_BUF_SIZE]; char connect_msg_buf[CONNECT_MSG_BUF_SIZE]; T_STRING *cas_log_buf = NULL; T_STRING *sql_buf = NULL; T_STRING *linebuf_tstr = NULL; char prepare_buf[128]; int i; char *msg_p; int lineno = 0; char read_flag = 1; char cur_date[32]; for (i = 0; i < MAX_SRV_HANDLE; i++) query_info_init (&query_info_buf[i]); cas_log_buf = t_string_make (1); sql_buf = t_string_make (1); linebuf_tstr = t_string_make (1000); if (cas_log_buf == NULL || sql_buf == NULL || linebuf_tstr == NULL) { fprintf (stderr, "malloc error\n"); goto log_top_err; } memset (client_msg_buf, 0, sizeof (client_msg_buf)); memset (connect_msg_buf, 0, sizeof (connect_msg_buf)); t_string_clear (cas_log_buf); t_string_clear (sql_buf); memset (prepare_buf, 0, sizeof (prepare_buf)); while (1) { if (read_flag) { if (ut_get_line (fp, linebuf_tstr, &linebuf, &lineno) <= 0) { break; } } read_flag = 1; if (!IS_CAS_LOG_CMD (linebuf)) continue; if (strncmp (linebuf + 23, "END OF LOG", 10) == 0) { break; } GET_CUR_DATE_STR (cur_date, linebuf); GET_MSG_START_PTR (msg_p, linebuf); if (strncmp (msg_p, "execute", 7) == 0 || strncmp (msg_p, "execute_all", 11) == 0 || strncmp (msg_p, "execute_call", 12) == 0 || strncmp (msg_p, "execute_batch", 13) == 0) { int qi_idx; char *query_p; int end_block_flag = 0; /* * execute log format: * <execute_cmd> srv_h_id <handle_id> <query_string> * bind <bind_index> : <TYPE> <VALUE> * <execute_cmd> [error:]<res> tuple <tuple_count> time <runtime_msec> * <execute_cmd>: * execute, execute_all or execute_call * * ex) * execute srv_h_id 1 select 'a' from db_root * bind 1 : VARCHAR test str * execute 0 tuple 1 time 0.004 */ qi_idx = log_execute (query_info_buf, linebuf, &query_p); if (qi_idx < 0 || query_p == NULL) goto log_top_err; t_string_clear (sql_buf); t_string_clear (cas_log_buf); t_string_add (sql_buf, query_p, strlen (query_p)); t_string_add (cas_log_buf, linebuf, strlen (linebuf)); if (read_multi_line_sql (fp, linebuf_tstr, &linebuf, &lineno, sql_buf, cas_log_buf) < 0) { break; } if (read_bind_value (fp, linebuf_tstr, &linebuf, &lineno, cas_log_buf) < 0) { break; } GET_MSG_START_PTR (msg_p, linebuf); /* skip query_cancel */ if (strncmp (msg_p, "query_cancel", 12) == 0) { if (ut_get_line (fp, linebuf_tstr, &linebuf, &lineno) <= 0) { break; } } if (strncmp (msg_p, "execute", 7) != 0) { while (1) { if (ut_get_line (fp, linebuf_tstr, &linebuf, &lineno) <= 0) { break; } GET_MSG_START_PTR (msg_p, linebuf); if (strncmp (msg_p, "***", 3) == 0) { end_block_flag = 1; if (ut_get_line (fp, linebuf_tstr, &linebuf, &lineno) <= 0) { /* ut_get_line error, just break; */ break; } break; } } } if (end_block_flag == 1) { continue; } query_info_buf[qi_idx].sql = (char *) REALLOC (query_info_buf[qi_idx].sql, t_string_len (sql_buf) + 1); strcpy (query_info_buf[qi_idx].sql, ut_trim (t_string_str (sql_buf))); GET_MSG_START_PTR (msg_p, linebuf); GET_CUR_DATE_STR (cur_date, linebuf); if (log_top_mode == MODE_MAX_HANDLE) { if (qi_idx >= mode_max_handle_lower_bound) { if (query_info_add (&query_info_buf[qi_idx], qi_idx + 1, 0, filename, lineno, cur_date) < 0) goto log_top_err; } } else { int execute_res, runtime; if (read_execute_end_msg (msg_p, &execute_res, &runtime) < 0) { if (query_info_add_ne (&query_info_buf[qi_idx], cur_date) < 0) goto log_top_err; read_flag = 0; continue; } if (t_string_add (cas_log_buf, linebuf, strlen (linebuf)) < 0) { goto log_top_err; } query_info_buf[qi_idx].cas_log = (char *) REALLOC (query_info_buf[qi_idx].cas_log, t_string_len (cas_log_buf) + 1); memcpy (query_info_buf[qi_idx].cas_log, t_string_str (cas_log_buf), t_string_len (cas_log_buf)); query_info_buf[qi_idx].cas_log_len = t_string_len (cas_log_buf); if (query_info_add (&query_info_buf[qi_idx], runtime, execute_res, filename, lineno, cur_date) < 0) { goto log_top_err; } } } } for (i = 0; i < MAX_SRV_HANDLE; i++) query_info_clear (&query_info_buf[i]); t_string_free (cas_log_buf); t_string_free (sql_buf); t_string_free (linebuf_tstr); return 0; log_top_err: t_string_free (cas_log_buf); t_string_free (sql_buf); t_string_free (linebuf_tstr); return -1; }