Ejemplo n.º 1
0
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);
	}
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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++;
		}
	}
}