static char * get_dns_string(netresolve_query_t query) { #ifdef USE_LDNS const uint8_t *answer; size_t length; if (!(answer = netresolve_query_get_dns_answer(query, &length))) return NULL; ldns_pkt *pkt; int status = ldns_wire2pkt(&pkt, answer, length); if (status) { fprintf(stderr, "ldns: %s", ldns_get_errorstr_by_id(status)); return NULL; } char *result = ldns_pkt2str(pkt); ldns_pkt_free(pkt); return result; #else return NULL; #endif }
/** helper function that logs a ldns_pkt packet to logfile */ static void log_pkt(const char* desc, ldns_pkt* pkt) { char* str = ldns_pkt2str(pkt); if(!str) log_info("%s: (failed)", desc); else { log_info("%s%s", desc, str); free(str); } }
char * compare_to_file(ldns_pkt *qp, ldns_pkt *pkt1, ldns_pkt *pkt2) { size_t iq, i1, i2, j, max_iq, max_i1, max_i2, max_j, k; char *pkt_str1 = ldns_pkt2str(pkt1); char *pkt_str2 = ldns_pkt2str(pkt2); char *pkt_query = ldns_pkt2str(qp); bool same = true; size_t match_count; char *match_words[MAX_MATCH_WORDS]; size_t match_word_count; bool done; size_t cur_file_nr; char *description; char *query_match; char *answer_match; max_iq = strlen(pkt_query); max_i1 = strlen(pkt_str1); max_i2 = strlen(pkt_str2); if (verbosity > 3) { printf("PACKET 1:\n"); ldns_pkt_print(stdout, pkt1); printf("\n\n\nPACKET 2:\n"); ldns_pkt_print(stdout, pkt2); printf("\n\n\n"); } for (cur_file_nr = 0; cur_file_nr < match_file_count; cur_file_nr++) { same = true; description = match_files[cur_file_nr].description; query_match = match_files[cur_file_nr].query_match; answer_match = match_files[cur_file_nr].answer_match; if (verbosity > 2) { printf("Trying: %s\n", description);\ } if (verbosity > 3) { printf("MATCH TO:\n"); printf("descr: %s\n", description); printf("QUERY:\n%s\n", query_match); printf("ANSWER:\n%s\n", answer_match); } /* first, try query match */ /* special case for unparseable queries */ if (!qp) { if (strncmp(query_match, "BADPACKET\n", 11) == 0 || strncmp(query_match, "*\n", 3) == 0 ) { same = true; } else { same = false; } goto querymatch; } max_j = strlen(query_match); iq = 0; j = 0; while (same && iq < max_iq && j < max_j) { if (pkt_query[iq] == ' ' || pkt_query[iq] == '\t' || pkt_query[iq] == '\n') { iq++; } else if (query_match[j] == ' ' || query_match[j] == '\t' || query_match[j] == '\n') { j++; } else if (pkt_query[iq] == query_match[j]) { iq++; j++; } else if (query_match[j] == '*') { j++; match_count = 1; while (query_match[j] == '*') { match_count++; if (j + 1 < max_j) { j++; } else { goto querymatch; } } while (query_match[j] == ' ' || query_match[j] == '\n' || query_match[j] == '\t') { if (j + 1 < max_j) { j++; } else { goto querymatch; } } while (strncmp(&pkt_query[iq], &query_match[j], match_count) != 0) { if (iq < max_iq) { iq++; } else { if (verbosity > 1) { printf("End of query packet reached while doing a * check\n"); } same = false; goto querymatch; } } } else if (query_match[j] == '[') { k = j + 1; done = false; match_word_count = 0; while (!done) { if (j < max_j) { j++; } else { fprintf(stderr, "Error: [ not closed\n"); exit(2); same = false; } if (query_match[j] == '|' || query_match[j] == ']') { if (match_word_count < MAX_MATCH_WORDS) { match_words[match_word_count] = strndup(&query_match[k], j - k); match_words[match_word_count][j-k] = 0; match_word_count++; k = j + 1; } else { fprintf(stderr, "Error, not more than %u match words (between [ and ]) allowed. Aborting\n", MAX_MATCH_WORDS); exit(3); } if (query_match[j] == ']') { done = true; } j++; } } while((pkt_query[iq] == ' ' || pkt_query[iq] == '\t' || pkt_query[iq] == '\n') && iq < max_iq) { if (iq < max_iq) { iq++; } else { if (verbosity > 1) { fprintf(stderr, "End query packet reached while looking for a match word ([])\n"); } same = false; goto match_word_done_iq; } } for (k = 0; k < match_word_count; k++) { if (strncmp(&pkt_query[iq], match_words[k], strlen(match_words[k])) == 0) { /* ok */ if (verbosity > 1) { printf("Found in 1, skipping\n"); } iq += strlen(match_words[k]); goto found_iq; } } found_iq: if (k == match_word_count) { if (verbosity > 1) { fprintf(stderr, "no match word found in query packet. Rest of packet:\n"); fprintf(stderr, "%s\n", &pkt_query[iq]); } same = false; } match_word_done_iq: for (k = 0; k < match_word_count; k++) { free(match_words[k]); } match_word_count = 0; } else if (query_match[j] == '?') { k = j + 1; while (query_match[j] != ' ' && query_match[j] != '\t' && query_match[j] != '\n' && j < max_j) { j++; } while((pkt_query[iq] == ' ' || pkt_query[iq] == '\t' || pkt_query[iq] == '\n') && iq < max_iq) { if (iq < max_iq) { iq++; } } if (iq + j - k < max_iq) { if (strncmp(&pkt_query[iq], &query_match[k], j - k) == 0) { iq += j - k; } } } else { if (verbosity > 1) { printf("Difference at iq: %u, j: %u, (%c != %c)\n", (unsigned int) iq, (unsigned int) j, pkt_query[iq], query_match[j]); } same = false; } } querymatch: if (same && verbosity > 0) { printf("query matches\n"); } /* ok the query matches, now look at both answers */ /* special case if one packet is null (ie. one server answers and one doesnt) */ if (same && (!pkt1 || !pkt2)) { if (strncmp(answer_match, "NOANSWER\n", 10) == 0 || strncmp(answer_match, "*\n", 3) == 0 ) { goto match; } else { same = false; if (verbosity > 4) { printf("no answer packet, no NOANSWER or * in spec.\n"); } } } max_j = strlen(answer_match); i1 = 0; i2 = 0; j = 0; while (same && i1 < max_i1 && i2 < max_i2 && j < max_j) { if (pkt_str1[i1] == ' ' || pkt_str1[i1] == '\t' || pkt_str1[i1] == '\n') { i1++; } else if (pkt_str2[i2] == ' ' || pkt_str2[i2] == '\t' || pkt_str2[i2] == '\n') { i2++; } else if (answer_match[j] == ' ' || answer_match[j] == '\t' || answer_match[j] == '\n') { j++; } else if (pkt_str1[i1] == pkt_str2[i2] && pkt_str2[i2] == answer_match[j]) { i1++; i2++; j++; } else if (answer_match[j] == '&') { j++; match_count = 1; while (answer_match[j] == '&') { match_count++; if (j + 1 < max_j) { j++; } else { /* TODO */ /* check sameness to end*/ if (verbosity >= 5) { printf("End of match reached in &\n"); } goto match; } } while (answer_match[j] == ' ' || answer_match[j] == '\t' || answer_match[j] == '\n') { if (j + 1 < max_j) { j++; } else { /* TODO */ /* check sameness to end*/ if (verbosity >= 5) { printf("End of match reached in & (2)\n"); } goto match; } } /* while (((answer_match[j] == '?' && !(strncmp(&pkt_str1[i1], &answer_match[j+1], match_count) != 0 || strncmp(&pkt_str2[i2], &answer_match[j+1], match_count) != 0)) || (strncmp(&pkt_str1[i1], &answer_match[j], match_count) != 0 && strncmp(&pkt_str2[i2], &answer_match[j], match_count) != 0)) && same */ while ((strncmp(&pkt_str1[i1], &answer_match[j], match_count) != 0 && strncmp(&pkt_str2[i2], &answer_match[j], match_count) != 0) && same ) { if (i1 < max_i1) { i1++; while ((pkt_str1[i1] == '\n' || pkt_str1[i1] == '\t' || pkt_str1[i1] == ' ' ) && i1 < max_i1) { i1++; } } else { if (verbosity > 1) { printf("End of pkt1 reached while doing an & check\n"); } same = false; } if (i2 < max_i2) { i2++; while ((pkt_str2[i2] == '\n' || pkt_str2[i2] == '\t' || pkt_str2[i2] == ' ' ) && i2 < max_i2) { i2++; } } else { if (verbosity > 1) { printf("End of pkt2 reached while doing an & check\n"); } same = false; } if (pkt_str1[i1] != pkt_str2[i2]) { if (verbosity > 1) { printf("Difference between the packets where they should be equal: %c != %c (%u, %u, & len: %u)\n", pkt_str1[i1], pkt_str2[i2], (unsigned int) i1, (unsigned int) i2, (unsigned int) match_count); } same = false; } } } else if (answer_match[j] == '*') { j++; match_count = 1; while (answer_match[j] == '*') { match_count++; if (j + 1 < max_j) { j++; } else { if (verbosity >= 5) { printf("End of match reached in *\n"); } goto match; } } while (answer_match[j] == ' ' || answer_match[j] == '\n' || answer_match[j] == '\t') { if (j + 1 < max_j) { j++; } else { if (verbosity >= 5) { printf("End of match reached in * (2)\n"); } goto match; } } while (strncmp(&pkt_str1[i1], &answer_match[j], match_count) != 0) { if (i1 < max_i1) { i1++; } else { if (verbosity > 1) { printf("End of pkt1 reached while doing a * check\n"); } same = false; goto match; } } while ((answer_match[j] == '?' && strncmp(&pkt_str2[i2], &answer_match[j + 1], match_count) != 0) || strncmp(&pkt_str2[i2], &answer_match[j], match_count) != 0) { if (i2 < max_i2) { i2++; } else { if (verbosity > 1) { printf("End of pkt2 reached while doing a * check\n"); } same = false; } } } else if (answer_match[j] == '[') { k = j + 1; done = false; match_word_count = 0; while (!done) { if (j < max_j) { j++; } else { fprintf(stderr, "Error: no match found for [\n"); exit(2); same = false; } if (answer_match[j] == '|' || answer_match[j] == ']') { if (match_word_count < MAX_MATCH_WORDS) { match_words[match_word_count] = strndup(&answer_match[k], j - k); match_words[match_word_count][j-k] = 0; match_word_count++; k = j + 1; } else { fprintf(stderr, "Error, not more than %u match words (between [ and ]) allowed. Aborting\n", MAX_MATCH_WORDS); exit(3); } if (answer_match[j] == ']') { done = true; } j++; } } while((pkt_str1[i1] == ' ' || pkt_str1[i1] == '\t' || pkt_str1[i1] == '\n') && i1 < max_i1) { if (i1 < max_i1) { i1++; } else { if (verbosity > 1) { fprintf(stderr, "End of pkt 1 reached while looking for a match word ([])\n"); } same = false; goto match_word_done; } } for (k = 0; k < match_word_count; k++) { if (strncmp(&pkt_str1[i1], match_words[k], strlen(match_words[k])) == 0) { /* ok */ if (verbosity > 1) { printf("Found %s in 1, skipping\n", match_words[k]); } i1 += strlen(match_words[k]); goto found1; } } found1: if (k >= match_word_count) { if (verbosity > 1) { fprintf(stderr, "no match word found in packet 1. Rest of packet:\n"); fprintf(stderr, "%s\n", &pkt_str1[i1]); } same = false; } while((pkt_str2[i2] == ' ' || pkt_str2[i2] == '\t' || pkt_str2[i2] == '\n') && i2 < max_i2) { if (i2 < max_i2) { i2++; } else { if (verbosity > 1) { fprintf(stderr, "End of pkt 2 reached while looking for a match word ([])\n"); } same = false; goto match_word_done; } } for (k = 0; k < match_word_count; k++) { if (strncmp(&pkt_str2[i2], match_words[k], strlen(match_words[k])) == 0) { /* ok */ if (verbosity > 1) { printf("Match word %s found in 2, skipping\n", match_words[k]); } i2 += strlen(match_words[k]); goto found2; } } found2: if (k >= match_word_count) { if (verbosity > 1) { fprintf(stdout, "no match word found in packet 2. Rest of packet:\n"); fprintf(stdout, "%s\n", &pkt_str2[i2]); } same = false; } match_word_done: for (k = 0; k < match_word_count; k++) { free(match_words[k]); } match_word_count = 0; } else if (answer_match[j] == '?' && answer_match[j+1] == '&' ) { j++; j++; k = j; while ((answer_match[j] != ' ' && answer_match[j] != '\t' && answer_match[j] != '\n' ) && j < max_j) { j++; } while((pkt_str1[i1] == ' ' || pkt_str1[i1] == '\t' || pkt_str1[i1] == '\n') && i1 < max_i1) { if (i1 < max_i1) { i1++; } } while((pkt_str2[i2] == ' ' || pkt_str2[i2] == '\t' || pkt_str2[i2] == '\n') && i2 < max_i2) { if (i2 < max_i2) { i2++; } } if (i1 + j - k < max_i1 && i2 + j - k < max_i2) { if (strncmp(&pkt_str1[i1], &answer_match[k], j - k) == 0 && strncmp(&pkt_str2[i2], &answer_match[k], j - k) == 0 ) { i1 += j - k; i2 += j - k; } } } else if (answer_match[j] == '?') { j++; k = j; while ((answer_match[j] != ' ' && answer_match[j] != '\t' && answer_match[j] != '\n' ) && j < max_j) { j++; } while((pkt_str1[i1] == ' ' || pkt_str1[i1] == '\t' || pkt_str1[i1] == '\n') && i1 < max_i1) { if (i1 < max_i1) { i1++; } } if (i1 + j - k < max_i1) { if (strncmp(&pkt_str1[i1], &answer_match[k], j - k) == 0) { i1 += j - k; } } while((pkt_str2[i2] == ' ' || pkt_str2[i2] == '\t' || pkt_str2[i2] == '\n') && i2 < max_i2) { if (i2 < max_i2) { i2++; } } if (i2 + j - k < max_i2) { if (strncmp(&pkt_str2[i2], &answer_match[k], j - k) == 0) { i2 += j - k; } } } else { if (verbosity > 1) { printf("Difference at i1: %u, i2: %u, j: %u (%c), (%c != %c)\n", (unsigned int) i1, (unsigned int) i2, (unsigned int) j, answer_match[j], pkt_str1[i1], pkt_str2[i2]); printf("rest of packet1:\n"); printf("%s\n\n\n", &pkt_str1[i1]); printf("rest of packet 2:\n"); printf("%s\n\n\n", &pkt_str2[i2]); printf("rest of match packet:\n"); printf("%s\n\n\n", &answer_match[j]); } same = false; } } if (same) { if (verbosity >= 5) { printf("Big while loop ended, we have match\n"); } goto match; } else { if (verbosity > 0) { printf("no match\n"); } if (verbosity > 0) { printf("REST OF MATCH: %s\n", &answer_match[j]); printf("REST OF PKT1: %s\n", &pkt_str1[i1]); printf("REST OF PKT2: %s\n", &pkt_str2[i2]); } } } LDNS_FREE(pkt_str1); LDNS_FREE(pkt_str2); LDNS_FREE(pkt_query); if (verbosity > 0) { printf("<<<<<<< NO MATCH >>>>>>>>\n"); printf("Query: %s\n", pkt_query); printf("Packet1:\n%s\n", pkt_str1); printf("Packet2:\n%s\n", pkt_str2); } return NULL; match: if (verbosity > 0) { printf("<<<<<<< MATCH!!! >>>>>>>>\n"); printf("Query: %s\n", pkt_query); printf("Packet1:\n%s\n", pkt_str1); printf("Packet2:\n%s\n", pkt_str2); printf("MATCHES BECAUSE: %s\n", description); printf("-------------------------\n\n\n"); } LDNS_FREE(pkt_str1); LDNS_FREE(pkt_str2); LDNS_FREE(pkt_query); return strdup(description); }
void compare(struct dns_info *d1, struct dns_info *d2) { ldns_pkt *p1, *p2, *pq; bool diff = false; char *pstr1, *pstr2; struct timeval now; char *compare_result; size_t file_nr; gettimeofday(&now, NULL); if (verbosity > 0) { printf("Id: %u\n", (unsigned int) d1->seq); } if (strcmp(d1->qdata, d2->qdata) != 0) { fprintf(stderr, "Query differs!\n"); fprintf(stdout, "q: %d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->qdata, d2->qdata); } else { if (strcmp(d1->adata, d2->adata) != 0) { if (advanced_match) { /* try to read the packet and sort the sections */ p1 = read_hex_pkt(d1->adata); p2 = read_hex_pkt(d2->adata); if (p1) { ldns_pkt_set_timestamp(p1, now); } if (p2) { ldns_pkt_set_timestamp(p2, now); } if (p1 && ldns_pkt_qdcount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_question(p1)); ldns_rr_list_sort(ldns_pkt_question(p1)); } if (p1 && ldns_pkt_ancount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_answer(p1)); ldns_rr_list_sort(ldns_pkt_answer(p1)); } if (p1 && ldns_pkt_nscount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_authority(p1)); ldns_rr_list_sort(ldns_pkt_authority(p1)); } if (p1 && ldns_pkt_arcount(p1) > 0) { ldns_rr_list2canonical(ldns_pkt_additional(p1)); ldns_rr_list_sort(ldns_pkt_additional(p1)); } if (p2 && ldns_pkt_qdcount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_question(p2)); ldns_rr_list_sort(ldns_pkt_question(p2)); } if (p2 && ldns_pkt_ancount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_answer(p2)); ldns_rr_list_sort(ldns_pkt_answer(p2)); } if (p2 && ldns_pkt_nscount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_authority(p2)); ldns_rr_list_sort(ldns_pkt_authority(p2)); } if (p2 && ldns_pkt_arcount(p2) > 0) { ldns_rr_list2canonical(ldns_pkt_additional(p2)); ldns_rr_list_sort(ldns_pkt_additional(p2)); } /* simply do string comparison first */ pstr1 = ldns_pkt2str(p1); pstr2 = ldns_pkt2str(p2); if ((!p1 && !p2) || strcmp(pstr1, pstr2) != 0) { /* okay strings still differ, get the query and do a match for the match files */ pq = read_hex_pkt(d1->qdata); compare_result = compare_to_file(pq, p1, p2); if (compare_result != NULL) { /*fprintf(stderr, compare_result);*/ if (compare_result[strlen(compare_result)-1] == '\n') { compare_result[strlen(compare_result)-1] = 0; } file_nr = add_known_difference(compare_result); if (store_known_differences) { fprintf(known_differences[file_nr].file, "q: %d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->adata, d2->adata); } free(compare_result); diff = false; } else { diff=false; printf("Error: Unknown difference in packet number %u:\n", (unsigned int) total_nr_of_packets); ldns_pkt_print(stdout, pq); printf("\n"); ldns_pkt_print(stdout, p1); printf("\n"); ldns_pkt_print(stdout, p2); printf("Quitting at packet %u\n", (unsigned int) d1->seq); exit(1); } ldns_pkt_free(pq); } else { sames++; } if (diff) { if (show_originals) { fprintf(stdout, "%d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->adata, d2->adata); } else { fprintf(stdout, "%d:%d\n", (int)d1->seq, (int)d2->seq); if (!dump_hex(stdout, p1)) { fprintf(stdout, "%s", d1->adata); } fprintf(stdout, "\n"); if (!dump_hex(stdout, p2)) { fprintf(stdout, "%s", d2->adata); } fprintf(stdout, "\n"); } } LDNS_FREE(pstr1); LDNS_FREE(pstr2); ldns_pkt_free(p1); ldns_pkt_free(p2); } else { fprintf(stdout, "%d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, d1->qdata, d1->adata, d2->adata); } } else { sames++; bytesames++; } } }