1 /*
2  * ldns-dpa inspects the (udp) DNS packets found in a pcap file
3  * and provides statistics about them
4  *
5  * (C) NLnet Labs 2006 - 2008
6  *
7  * See the file LICENSE for the license
8  */
9 #include "config.h"
10 
11 #include <ldns/ldns.h>
12 
13 #ifdef HAVE_PCAP_H
14 #ifdef HAVE_LIBPCAP
15 #include "ldns-dpa.h"
16 
17 #ifdef HAVE_NETINET_IP6_H
18 #include <netinet/ip6.h>
19 #endif
20 #include <errno.h>
21 
22 #ifndef IP_OFFMASK
23 #define IP_OFFMASK 0x1fff
24 #endif
25 
26 int verbosity = 1;
27 
28 #define ETHER_HEADER_LENGTH 14
29 #define UDP_HEADER_LENGTH 8
30 #define IP6_HEADER_LENGTH 40
31 
32 /* some systems don't have this? */
33 #ifndef ETHERTYPE_IPV6
34 #define ETHERTYPE_IPV6 0x86dd
35 #endif
36 
37 #define MAX_MATCHES 20
38 #define MAX_OPERATORS 7
39 
40 
41 /* global options */
42 bool show_filter_matches = false;
43 size_t total_nr_of_dns_packets = 0;
44 size_t total_nr_of_filtered_packets = 0;
45 size_t not_ip_packets = 0;
46 size_t bad_dns_packets = 0;
47 size_t arp_packets = 0;
48 size_t udp_packets = 0;
49 size_t tcp_packets = 0;
50 size_t fragmented_packets = 0;
51 size_t lost_packet_fragments = 0;
52 FILE *hexdumpfile = NULL;
53 pcap_dumper_t *dumper = NULL;
54 pcap_dumper_t *not_ip_dump = NULL;
55 pcap_dumper_t *bad_dns_dump = NULL;
56 
57 
58 struct
59 fragment_part {
60 	uint16_t ip_id;
61 	uint8_t data[65536];
62 	size_t cur_len;
63 };
64 
65 struct fragment_part *fragment_p;
66 
67 /* To add a match,
68  * - add it to the enum
69  * - add it to the table_matches const
70  * - add a handler to value_matches
71  * - tell in get_string_value() where in the packet the data lies
72  * - add to parser?
73  * - add to show_match_ function
74  */
75 enum enum_match_ids {
76 	MATCH_ID,
77 	MATCH_OPCODE,
78 	MATCH_RCODE,
79 	MATCH_PACKETSIZE,
80 	MATCH_QR,
81 	MATCH_TC,
82 	MATCH_AD,
83 	MATCH_CD,
84 	MATCH_RD,
85 	MATCH_EDNS,
86 	MATCH_EDNS_PACKETSIZE,
87 	MATCH_DO,
88 	MATCH_QUESTION_SIZE,
89 	MATCH_ANSWER_SIZE,
90 	MATCH_AUTHORITY_SIZE,
91 	MATCH_ADDITIONAL_SIZE,
92 	MATCH_SRC_ADDRESS,
93 	MATCH_DST_ADDRESS,
94 	MATCH_TIMESTAMP,
95 	MATCH_QUERY,
96 	MATCH_QTYPE,
97 	MATCH_QNAME,
98 	MATCH_ANSWER,
99 	MATCH_AUTHORITY,
100 	MATCH_ADDITIONAL,
101 	MATCH_LAST
102 };
103 typedef enum enum_match_ids match_id;
104 
105 enum enum_counter_types {
106 	TYPE_INT,
107 	TYPE_BOOL,
108 	TYPE_OPCODE,
109 	TYPE_RCODE,
110 	TYPE_STRING,
111 	TYPE_TIMESTAMP,
112 	TYPE_ADDRESS,
113 	TYPE_RR,
114 	TYPE_RR_TYPE,
115 	TYPE_LAST
116 };
117 typedef enum enum_counter_types counter_type;
118 
119 const ldns_lookup_table lt_types[] = {
120 	{TYPE_INT, "int" },
121 	{TYPE_BOOL, "bool" },
122 	{TYPE_OPCODE, "opcode" },
123 	{TYPE_RCODE, "rcode" },
124 	{TYPE_STRING, "string" },
125 	{TYPE_TIMESTAMP, "timestamp" },
126 	{TYPE_ADDRESS, "address" },
127 	{TYPE_RR, "rr" },
128 	{ 0, NULL }
129 };
130 
131 enum enum_type_operators {
132 	OP_EQUAL,
133 	OP_NOTEQUAL,
134 	OP_GREATER,
135 	OP_LESSER,
136 	OP_GREATEREQUAL,
137 	OP_LESSEREQUAL,
138 	OP_CONTAINS,
139 	OP_LAST
140 };
141 typedef enum enum_type_operators type_operator;
142 
143 const ldns_lookup_table lt_operators[] = {
144 	{ OP_EQUAL, "=" },
145 	{ OP_NOTEQUAL, "!=" },
146 	{ OP_GREATER, ">" },
147 	{ OP_LESSER, "<" },
148 	{ OP_GREATEREQUAL, ">=" },
149 	{ OP_LESSEREQUAL, "<=" },
150 	{ OP_CONTAINS, "~=" },
151 	{ 0, NULL }
152 };
153 
get_op_str(type_operator op)154 static const char *get_op_str(type_operator op) {
155 	const ldns_lookup_table *lt;
156 	lt = ldns_lookup_by_id((ldns_lookup_table *) lt_operators, op);
157 	if (lt) {
158 		return lt->name;
159 	} else {
160 		fprintf(stderr, "Unknown operator id: %u\n", op);
161 		exit(1);
162 	}
163 }
164 
165 static type_operator
get_op_id(char * op_str)166 get_op_id(char *op_str)
167 {
168 	const ldns_lookup_table *lt;
169 	lt = ldns_lookup_by_name((ldns_lookup_table *) lt_operators, op_str);
170 	if (lt) {
171 		return (type_operator) lt->id;
172 	} else {
173 		fprintf(stderr, "Unknown operator: %s\n", op_str);
174 		exit(1);
175 	}
176 }
177 
178 struct struct_type_operators {
179 	counter_type type;
180 	size_t operator_count;
181 	type_operator operators[10];
182 };
183 typedef struct struct_type_operators type_operators;
184 
185 const type_operators const_type_operators[] = {
186 	{ TYPE_INT, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } },
187 	{ TYPE_BOOL, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} },
188 	{ TYPE_OPCODE, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} },
189 	{ TYPE_RCODE, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} },
190 	{ TYPE_STRING, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} },
191 	{ TYPE_TIMESTAMP, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } },
192 	{ TYPE_ADDRESS, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} },
193 	{ TYPE_RR, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} },
194 	{ TYPE_RR_TYPE, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } },
195 	{ 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
196 };
197 
198 const type_operators *
get_type_operators(counter_type type)199 get_type_operators(counter_type type) {
200 	const type_operators *to = const_type_operators;
201 	while (to) {
202 		if (to->type == type) {
203 			return to;
204 		}
205 		to++;
206 	}
207 	return NULL;
208 }
209 
210 struct struct_match_table {
211 	match_id id;
212 	const char *name;
213 	const char *description;
214 	const counter_type type;
215 };
216 typedef struct struct_match_table match_table;
217 
218 /* order of entries has been changed after gprof analysis, and reasoning
219  * about the uses of -u arguments
220  */
221 const match_table matches[] = {
222 	{ MATCH_QUERY, "query", "String representation of the query RR", TYPE_RR },
223 	{ MATCH_QTYPE, "qtype", "RR Type of the question RR, if present", TYPE_RR_TYPE },
224 	{ MATCH_QNAME, "qname", "Owner name of the question RR, if present", TYPE_STRING },
225 	{ MATCH_SRC_ADDRESS, "srcaddress", "address the packet was sent from", TYPE_ADDRESS },
226 	{ MATCH_TIMESTAMP, "timestamp", "time the packet was sent", TYPE_TIMESTAMP },
227 	{ MATCH_DST_ADDRESS, "dstaddress", "address the packet was sent to", TYPE_ADDRESS },
228 	{ MATCH_EDNS_PACKETSIZE, "edns-packetsize", "packets size specified in edns rr", TYPE_INT },
229 	{ MATCH_ID, "id", "id of the packet", TYPE_INT },
230 	{ MATCH_OPCODE, "opcode", "opcode of packet (rfc1035)", TYPE_OPCODE },
231 	{ MATCH_RCODE, "rcode", "response code of packet", TYPE_RCODE },
232 	{ MATCH_PACKETSIZE, "packetsize", "size of packet in bytes", TYPE_INT },
233 	{ MATCH_QR, "qr", "value of qr bit", TYPE_BOOL },
234 	{ MATCH_TC, "tc", "value of tc bit", TYPE_BOOL },
235 	{ MATCH_AD, "ad", "value of ad bit", TYPE_BOOL },
236 	{ MATCH_CD, "cd", "value of cd bit", TYPE_BOOL },
237 	{ MATCH_RD, "rd", "value of rd bit", TYPE_BOOL },
238 	{ MATCH_EDNS, "edns", "existence of edns rr", TYPE_BOOL },
239 	{ MATCH_DO, "do", "value of do bit", TYPE_BOOL },
240 	{ MATCH_QUESTION_SIZE, "questionsize", "number of rrs in the question section", TYPE_INT },
241 	{ MATCH_ANSWER_SIZE, "answersize", "number of rrs in the answer section", TYPE_INT },
242 	{ MATCH_AUTHORITY_SIZE, "authoritysize", "number of rrs in the authority section", TYPE_INT },
243 	{ MATCH_ADDITIONAL_SIZE, "additionalsize", "number of rrs in the additional section", TYPE_INT },
244 	{ MATCH_ANSWER, "answer", "String representation of the answer RRs", TYPE_RR },
245 	{ MATCH_AUTHORITY, "authority", "String representation of the authority RRs", TYPE_RR },
246 	{ MATCH_ADDITIONAL, "additional", "String representation of the additional RRs", TYPE_RR },
247 	{ 0, NULL , NULL, TYPE_INT}
248 };
249 
250 enum enum_match_expression_operators {
251 	MATCH_EXPR_OR,
252 	MATCH_EXPR_AND,
253 	MATCH_EXPR_LEAF
254 };
255 typedef enum enum_match_expression_operators match_expression_operator;
256 
257 struct struct_match_operation {
258 	match_id id;
259 	type_operator operator;
260 	char *value;
261 };
262 typedef struct struct_match_operation match_operation;
263 
264 typedef struct struct_match_expression match_expression;
265 struct struct_match_expression {
266 	/* and or or, or leaf (in which case there are no subtrees, but only a match_table */
267 	match_expression_operator op;
268 	match_expression *left;
269 	match_expression *right;
270 	match_operation *match;
271 	size_t count;
272 };
273 
274 typedef struct struct_match_counters match_counters;
275 struct struct_match_counters {
276 /*
277 	match_expression **counter;
278 	size_t size;
279 */
280 	match_expression *match;
281 	match_counters *left;
282 	match_counters *right;
283 };
284 
285 match_table *
get_match_by_name(char * name)286 get_match_by_name(char *name) {
287 	match_table *mt = (match_table *) matches;
288 	if (name) {
289 		while (mt->name != NULL) {
290 			if (strcasecmp(name, mt->name) == 0) {
291 				return mt;
292 			}
293 			mt++;
294 		}
295 	}
296 	return NULL;
297 }
298 
299 static match_table *
get_match_by_id(match_id id)300 get_match_by_id(match_id id) {
301 	match_table *mt = (match_table *) matches;
302 
303 	while (mt->name != NULL) {
304 		if (mt->id == id) {
305 			return mt;
306 		}
307 		mt++;
308 	}
309 	return NULL;
310 }
311 
312 static const char *
get_match_name_str(match_id id)313 get_match_name_str(match_id id) {
314 	match_table *mt = get_match_by_id(id);
315 	if (mt) {
316 		return mt->name;
317 	} else {
318 		fprintf(stderr, "Unknown match id: %u\n", id);
319 		exit(1);
320 		return "Unknown match id";
321 	}
322 }
323 
324 static void
print_match_operation(FILE * output,match_operation * mc)325 print_match_operation(FILE *output, match_operation *mc)
326 {
327 	match_table *mt = NULL;
328 	ldns_lookup_table *lt;
329 	struct timeval time;
330 	time_t time_tt;
331 	int value;
332 	size_t pos;
333 	char *tmp, *tmp2;
334 
335 	if (mc) {
336 		mt = get_match_by_id(mc->id);
337 
338 		if (mt) {
339 			fprintf(output, "%s %s ",mt->name, get_op_str(mc->operator));
340 
341 			switch (mt->type) {
342 				case TYPE_INT:
343 				case TYPE_STRING:
344 				case TYPE_ADDRESS:
345 				case TYPE_RR:
346 					fprintf(output, "'%s'", mc->value);
347 					break;
348 				case TYPE_BOOL:
349 					if (strncmp(mc->value, "1", 2) == 0) {
350 						fprintf(output,"'true'");
351 					} else {
352 						fprintf(output,"'false'");
353 					}
354 					break;
355 				case TYPE_OPCODE:
356 					value = atoi(mc->value);
357 					lt = ldns_lookup_by_id(ldns_opcodes, value);
358 					if (lt) {
359 						fprintf(output, "%s", lt->name);
360 					} else {
361 						fprintf(output, "%s", mc->value);
362 					}
363 					break;
364 				case TYPE_RCODE:
365 					value = atoi(mc->value);
366 					lt = ldns_lookup_by_id(ldns_rcodes, value);
367 					if (lt) {
368 						fprintf(output, "%s", lt->name);
369 					} else {
370 						fprintf(output, "%s", mc->value);
371 					}
372 					break;
373 				case TYPE_TIMESTAMP:
374 #ifndef S_SPLINT_S
375 					time.tv_sec = (long int) atol(mc->value);
376 #endif
377 					time_tt = (time_t)time.tv_sec;
378 					tmp = ctime(&time_tt);
379 					tmp2 = malloc(strlen(tmp) + 1);
380 					for (pos = 0; pos < strlen(tmp); pos++) {
381 						if (tmp[pos] == '\n') {
382 							tmp2[pos] = '\0';
383 						} else {
384 							tmp2[pos] = tmp[pos];
385 						}
386 					}
387 					tmp2[pos] = '\0';
388 					fprintf(output, "%s", tmp2);
389 					free(tmp2);
390 					break;
391 				default:
392 				fprintf(output, "'%s'", mc->value);
393 			}
394 
395 		} else {
396 			fprintf(output, "%u %s '%s'", mc->id, get_op_str(mc->operator), mc->value);
397 		}
398 	} else {
399 		fprintf(output, "(nil)");
400 	}
401 }
402 
403 static void
print_match_expression(FILE * output,match_expression * expr)404 print_match_expression(FILE *output, match_expression *expr)
405 {
406 	if (expr) {
407 		switch (expr->op) {
408 			case MATCH_EXPR_OR:
409 				fprintf(output, "(");
410 				print_match_expression(output, expr->left);
411 				fprintf(output, " | ");
412 				print_match_expression(output, expr->right);
413 				fprintf(output, ")");
414 				break;
415 			case MATCH_EXPR_AND:
416 				fprintf(output, "(");
417 				print_match_expression(output, expr->left);
418 				fprintf(output, " & ");
419 				print_match_expression(output, expr->right);
420 				fprintf(output, ")");
421 				break;
422 			case MATCH_EXPR_LEAF:
423 				print_match_operation(output, expr->match);
424 				break;
425 			default:
426 /*
427 				fprintf(output, "ERROR PRINTING MATCH: unknown op: %u\n", expr->op);
428 				exit(1);
429 */
430 				fprintf(output, "(");
431 if (expr->left) {
432 	print_match_expression(output, expr->left);
433 }
434 				fprintf(output, " ? ");
435 if (expr->right) {
436 	print_match_expression(output, expr->right);
437 }
438 				fprintf(output, ") _");
439 if (expr->match) {
440 	print_match_operation(output, expr->match);
441 }
442 fprintf(output, "_");
443 		}
444 	} else {
445 		printf("(nil)");
446 	}
447 }
448 
449 static void
print_counters(FILE * output,match_counters * counters,bool show_percentages,size_t total,int count_minimum)450 print_counters(FILE *output, match_counters *counters, bool show_percentages, size_t total, int count_minimum)
451 {
452 	double percentage;
453 
454 	if (!counters || !output) {
455 		return;
456 	}
457 
458 	if (counters->left) {
459 		print_counters(output, counters->left, show_percentages, total, count_minimum);
460 	}
461 	if (counters->match) {
462 		if (count_minimum < (int) counters->match->count) {
463 			print_match_expression(output, counters->match);
464 			printf(": %u", (unsigned int) counters->match->count);
465 			if (show_percentages) {
466 				percentage = (double) counters->match->count / (double) total * 100.0;
467 				printf(" (%.2f%%)", percentage);
468 			}
469 			printf("\n");
470 		}
471 	}
472 	if (counters->right) {
473 		print_counters(output, counters->right, show_percentages, total, count_minimum);
474 	}
475 
476 	return;
477 }
478 
479 static void
ldns_pkt2file_hex(FILE * fp,const ldns_pkt * pkt)480 ldns_pkt2file_hex(FILE *fp, const ldns_pkt *pkt)
481 {
482 	uint8_t *wire;
483 	size_t size, i;
484 	ldns_status status;
485 
486 	status = ldns_pkt2wire(&wire, pkt, &size);
487 
488 	if (status != LDNS_STATUS_OK) {
489 		fprintf(stderr, "Unable to convert packet: error code %u", status);
490 		return;
491 	}
492 
493 	fprintf(fp, "; 0");
494 	for (i = 1; i < 20; i++) {
495 		fprintf(fp, " %2u", (unsigned int) i);
496 	}
497 	fprintf(fp, "\n");
498 	fprintf(fp, ";--");
499 	for (i = 1; i < 20; i++) {
500 		fprintf(fp, " --");
501 	}
502 	fprintf(fp, "\n");
503 	for (i = 0; i < size; i++) {
504 		if (i % 20 == 0 && i > 0) {
505 			fprintf(fp, "\t; %4u-%4u\n", (unsigned int) i-19, (unsigned int) i);
506 		}
507 		fprintf(fp, " %02x", (unsigned int)wire[i]);
508 	}
509 	fprintf(fp, "\n\n");
510 }
511 
512 /*
513  * Calculate the total for all match operations with the same id as this one
514  * (if they are 'under' this one in the tree, which should be the case in
515  * the unique counter tree
516  */
517 static size_t
calculate_total_value(match_counters * counters,match_operation * cur)518 calculate_total_value(match_counters *counters, match_operation *cur)
519 {
520 	size_t result = 0;
521 
522 	if (!counters) {
523 		return 0;
524 	}
525 
526 	if (counters->match->match->id == cur->id) {
527 		result = (size_t) atol(counters->match->match->value) * counters->match->count;
528 	}
529 
530 	if (counters->left) {
531 		result += calculate_total_value(counters->left, cur);
532 	}
533 	if (counters->right) {
534 		result += calculate_total_value(counters->right, cur);
535 	}
536 
537 	return result;
538 }
539 
540 static size_t
calculate_total_count_matches(match_counters * counters,match_operation * cur)541 calculate_total_count_matches(match_counters *counters, match_operation *cur)
542 {
543 	size_t result = 0;
544 
545 	if (!counters) {
546 		return 0;
547 	}
548 
549 	if (counters->match->match->id == cur->id) {
550 		result = 1;
551 	}
552 
553 	if (counters->left) {
554 		/* In some cases, you don't want the number of actual
555 		   counted matches, for instance when calculating the
556 		   average number of queries per second. In this case
557 		   you want the number of seconds */
558 		if (cur->id == MATCH_TIMESTAMP) {
559 			result += (size_t) abs((int) (atol(counters->match->match->value) - atol(counters->left->match->match->value))) - 1;
560 		}
561 		result += calculate_total_count_matches(counters->left, cur);
562 	}
563 	if (counters->right) {
564 		if (cur->id == MATCH_TIMESTAMP) {
565 			result += (size_t) abs((int) (atol(counters->right->match->match->value) - atol(counters->match->match->value))) - 1;
566 		}
567 		result += calculate_total_count_matches(counters->right, cur);
568 	}
569 
570 	return result;
571 }
572 
573 /**
574  * Returns true if there is a previous match operation with the given type
575  * in the counters structure
576  */
577 static bool
has_previous_match(match_counters * counters,match_operation * cur)578 has_previous_match(match_counters *counters, match_operation *cur)
579 {
580 	if (!counters) {
581 		return false;
582 	}
583 
584 	if (counters->left) {
585 		if (counters->left->match->match->id == cur->id) {
586 			return true;
587 		} else if (has_previous_match(counters->left, cur)) {
588 			return true;
589 		} else if (counters->left->right) {
590 			if (counters->left->right->match->match->id == cur->id) {
591 				return true;
592 			} else if (has_previous_match(counters->left->right, cur)) {
593 				return true;
594 			}
595 		}
596 	}
597 	return false;
598 }
599 
600 /**
601  * Returns true if there is a later match operation with the given type
602  * in the counters structure
603  */
604 static bool
has_next_match(match_counters * counters,match_operation * cur)605 has_next_match(match_counters *counters, match_operation *cur)
606 {
607 	if (!counters) {
608 		return false;
609 	}
610 
611 	if (counters->right) {
612 		if (counters->right->match->match->id == cur->id) {
613 			return true;
614 		} else if (has_next_match(counters->right, cur)) {
615 			return true;
616 		} else if (counters->right->left) {
617 			if (counters->right->left->match->match->id == cur->id) {
618 				return true;
619 			} else if (has_next_match(counters->right->left, cur)) {
620 				return true;
621 			}
622 		}
623 	}
624 	return false;
625 }
626 
627 /**
628  * Returns the first match with the same type at *cur in
629  * the counter list, or NULL if it is not found
630  */
631 static match_expression *
get_first_match_expression(match_counters * counters,match_operation * cur)632 get_first_match_expression(match_counters *counters, match_operation *cur)
633 {
634 	if (!counters) {
635 		return NULL;
636 	}
637 
638 	if (has_previous_match(counters, cur)) {
639 		return get_first_match_expression(counters->left, cur);
640 	} else if (counters->match->match->id == cur->id) {
641 		return counters->match;
642 	} else if (counters->right) {
643 		return get_first_match_expression(counters->right, cur);
644 	} else {
645 		return NULL;
646 	}
647 }
648 
649 /**
650  * Returns the second match expression with the same type at *cur in
651  * the counter list, or NULL if it is not found
652  */
653 static match_expression *
get_second_match_expression(match_counters * counters,match_operation * cur)654 get_second_match_expression(match_counters *counters, match_operation *cur)
655 {
656 	if (!counters) {
657 		return NULL;
658 	}
659 
660 	if (has_previous_match(counters, cur)) {
661 		if (has_previous_match(counters->left, cur)) {
662 			return get_second_match_expression(counters->left, cur);
663 		} else {
664 			return counters->left->match;
665 		}
666 /*
667 	} else if (counters->match->match->id == cur->id) {
668 		return counters->match->match->value;
669 */	} else if (counters->right) {
670 		return get_first_match_expression(counters->right, cur);
671 	} else {
672 		return NULL;
673 	}
674 }
675 
676 /**
677  * Returns the last match expression with the same type at *cur in
678  * the counter list, or NULL if it is not found
679  */
680 static match_expression *
get_last_match_expression(match_counters * counters,match_operation * cur)681 get_last_match_expression(match_counters *counters, match_operation *cur)
682 {
683 	if (!counters) {
684 		return NULL;
685 	}
686 
687 	if (has_next_match(counters, cur)) {
688 		return get_last_match_expression(counters->right, cur);
689 	} else if (counters->match->match->id == cur->id) {
690 		return counters->match;
691 	} else if (counters->left) {
692 		return get_last_match_expression(counters->left, cur);
693 	} else {
694 		return NULL;
695 	}
696 }
697 
698 /**
699  * Returns the last but one match expression with the same type at *cur in
700  * the counter list, or NULL if it is not found
701  */
702 static match_expression *
get_last_but_one_match_expression(match_counters * counters,match_operation * cur)703 get_last_but_one_match_expression(match_counters *counters, match_operation *cur)
704 {
705 	if (!counters) {
706 		return NULL;
707 	}
708 
709 	if (has_next_match(counters, cur)) {
710 		if (has_next_match(counters->right, cur)) {
711 			return get_last_but_one_match_expression(counters->right, cur);
712 		} else {
713 			return counters->match;
714 		}
715 /*
716 	} else if (counters->match->match->id == cur->id) {
717 		return counters->match->match->value;
718 */	} else if (counters->left) {
719 		return get_last_match_expression(counters->right, cur);
720 	} else {
721 		return NULL;
722 	}
723 }
724 
725 static size_t
get_first_count(match_counters * counters,match_operation * cur)726 get_first_count(match_counters *counters, match_operation *cur)
727 {
728 	match_expression *o = get_first_match_expression(counters, cur);
729 	if (o) {
730 		return o->count;
731 	} else {
732 		return 0;
733 	}
734 }
735 
736 static size_t
get_last_count(match_counters * counters,match_operation * cur)737 get_last_count(match_counters *counters, match_operation *cur)
738 {
739 	match_expression *o = get_last_match_expression(counters, cur);
740 	if (o) {
741 		return o->count;
742 	} else {
743 		return 0;
744 	}
745 }
746 
747 
748 static size_t
calculate_total_count(match_counters * counters,match_operation * cur)749 calculate_total_count(match_counters *counters, match_operation *cur)
750 {
751 	size_t result = 0;
752 
753 	if (!counters) {
754 		return 0;
755 	}
756 
757 	if (counters->match->match->id == cur->id) {
758 		result = counters->match->count;
759 	}
760 
761 	if (counters->left) {
762 		result += calculate_total_count(counters->left, cur);
763 	}
764 	if (counters->right) {
765 		result += calculate_total_count(counters->right, cur);
766 	}
767 
768 	return result;
769 }
770 
771 static void
print_counter_averages(FILE * output,match_counters * counters,match_operation * cur)772 print_counter_averages(FILE *output, match_counters *counters, match_operation *cur)
773 {
774 	size_t total_value;
775 	size_t total_count;
776 	match_table *mt;
777 
778 	if (!counters || !output) {
779 		return;
780 	}
781 
782 	if (!cur) {
783 		cur = counters->match->match;
784 		mt = get_match_by_id(cur->id);
785 		total_value = calculate_total_value(counters, cur);
786 		total_count = calculate_total_count(counters, cur);
787 		printf("Average for %s: (%u / %u) %.02f\n", mt->name, (unsigned int) total_value, (unsigned int) total_count, (float) total_value / (float) total_count);
788 		if (counters->left) {
789 			print_counter_averages(output, counters->left, cur);
790 		}
791 		if (counters->right) {
792 			print_counter_averages(output, counters->right, cur);
793 		}
794 	} else {
795 		if (counters->left) {
796 			if (counters->left->match->match->id != cur->id) {
797 				print_counter_averages(output, counters->left, NULL);
798 			}
799 		}
800 		if (counters->right) {
801 			if (counters->right->match->match->id != cur->id) {
802 				print_counter_averages(output, counters->right, NULL);
803 			}
804 		}
805 	}
806 
807 	return;
808 }
809 
810 static void
print_counter_average_count(FILE * output,match_counters * counters,match_operation * cur,bool remove_first_last)811 print_counter_average_count(FILE *output, match_counters *counters, match_operation *cur, bool remove_first_last)
812 {
813 	size_t total_matches;
814 	size_t total_count;
815 	match_table *mt;
816 
817 	if (!counters || !output) {
818 		return;
819 	}
820 
821 	if (!cur) {
822 		cur = counters->match->match;
823 		mt = get_match_by_id(cur->id);
824 		total_matches = calculate_total_count_matches(counters, cur);
825 		total_count = calculate_total_count(counters, cur);
826 		/* Remove the first and last for instance for timestamp average counts (half seconds drag down the average) */
827 		if (remove_first_last) {
828 			total_count -= get_first_count(counters, cur);
829 			total_count -= get_last_count(counters, cur);
830 			printf("Removing first count from average: %u\n", (unsigned int) get_first_count(counters,cur));
831 			printf("Removing last count from average: %u\n", (unsigned int) get_last_count(counters,cur));
832 			/* in the case where we count the differences between match values too
833 			 * (like with timestamps) we need to subtract from the match count too
834 			 */
835 			if (cur->id == MATCH_TIMESTAMP) {
836 				if (get_first_match_expression(counters, cur) && get_second_match_expression(counters, cur)) {
837 					total_matches -= atol(get_second_match_expression(counters, cur)->match->value) - atol(get_first_match_expression(counters, cur)->match->value);
838 				}
839 				if (get_last_match_expression(counters, cur) && get_last_but_one_match_expression(counters, cur)) {
840 					total_matches -= atol(get_last_match_expression(counters, cur)->match->value) - atol(get_last_but_one_match_expression(counters, cur)->match->value);
841 				}
842 			} else {
843 				total_matches -= 2;
844 			}
845 		}
846 		printf("Average count for %s: (%u / %u) %.02f\n", mt->name, (unsigned int) total_count, (unsigned int) total_matches, (float) total_count / (float) total_matches);
847 		if (counters->left) {
848 			print_counter_averages(output, counters->left, cur);
849 		}
850 		if (counters->right) {
851 			print_counter_averages(output, counters->right, cur);
852 		}
853 	} else {
854 		if (counters->left) {
855 			if (counters->left->match->match->id != cur->id) {
856 				print_counter_averages(output, counters->left, NULL);
857 			}
858 		}
859 		if (counters->right) {
860 			if (counters->right->match->match->id != cur->id) {
861 				print_counter_averages(output, counters->right, NULL);
862 			}
863 		}
864 	}
865 
866 	return;
867 }
868 
869 static bool
match_int(type_operator operator,char * value,char * mvalue)870 match_int(type_operator operator,
871           char *value,
872 	  char *mvalue)
873 {
874 	int a, b;
875 
876 	if (!value || !mvalue) {
877 		return false;
878 	}
879 
880 	a = atoi(value);
881 	b = atoi(mvalue);
882 
883 	switch (operator) {
884 		case OP_EQUAL:
885 			return a == b;
886 			break;
887 		case OP_NOTEQUAL:
888 			return a != b;
889 			break;
890 		case OP_GREATER:
891 			return a > b;
892 			break;
893 		case OP_LESSER:
894 			return a < b;
895 			break;
896 		case OP_GREATEREQUAL:
897 			return a >= b;
898 			break;
899 		case OP_LESSEREQUAL:
900 			return a <= b;
901 			break;
902 		default:
903 			fprintf(stderr, "Unknown operator: %u\n", operator);
904 			exit(2);
905 	}
906 }
907 
908 static bool
match_opcode(type_operator operator,char * value,char * mvalue)909 match_opcode(type_operator operator,
910              char *value,
911              char *mvalue)
912 {
913 	ldns_pkt_opcode a, b;
914 	int i;
915 	ldns_lookup_table *lt;
916 
917 	/* try parse name first, then parse as int */
918 	lt = ldns_lookup_by_name(ldns_opcodes, value);
919 	if (lt) {
920 		a = lt->id;
921 	} else {
922 		i = atoi(value);
923 		if (i >= 0 && isdigit((unsigned char)value[0])) {
924 			lt = ldns_lookup_by_id(ldns_opcodes, i);
925 			if (lt) {
926 				a = lt->id;
927 			} else {
928 				fprintf(stderr, "Unknown opcode: %s\n", value);
929 				exit(1);
930 				return false;
931 			}
932 		} else {
933 			fprintf(stderr, "Unknown opcode: %s\n", value);
934 			exit(1);
935 			return false;
936 		}
937 	}
938 
939 	lt = ldns_lookup_by_name(ldns_opcodes, mvalue);
940 	if (lt) {
941 		b = lt->id;
942 	} else {
943 		i = atoi(mvalue);
944 		if (i >= 0 && isdigit((unsigned char)mvalue[0])) {
945 			lt = ldns_lookup_by_id(ldns_opcodes, i);
946 			if (lt) {
947 				b = lt->id;
948 			} else {
949 				fprintf(stderr, "Unknown opcode: %s\n", mvalue);
950 				exit(1);
951 				return false;
952 			}
953 		} else {
954 			fprintf(stderr, "Unknown opcode: %s\n", mvalue);
955 			exit(1);
956 			return false;
957 		}
958 	}
959 
960 	switch(operator) {
961 		case OP_EQUAL:
962 			return a == b;
963 			break;
964 		case OP_NOTEQUAL:
965 			return a != b;
966 			break;
967 		default:
968 			fprintf(stderr, "Error bad operator for opcode: %s\n", get_op_str(operator));
969 			return false;
970 			break;
971 	}
972 }
973 
974 static bool
match_str(type_operator operator,char * value,char * mvalue)975 match_str(type_operator operator,
976           char *value,
977           char *mvalue)
978 {
979 	char *valuedup, *mvaluedup;
980 	size_t i;
981 	bool result;
982 
983 	if (operator == OP_CONTAINS) {
984 		/* strcasestr is not C89
985 		return strcasestr(value, mvalue) != 0;
986 		*/
987 		valuedup = strdup(value);
988 		mvaluedup = strdup(mvalue);
989 		for (i = 0; i < strlen(valuedup); i++) {
990 			valuedup[i] = tolower((unsigned char)valuedup[i]);
991 		}
992 		for (i = 0; i < strlen(mvaluedup); i++) {
993 			mvaluedup[i] = tolower((unsigned char)mvaluedup[i]);
994 		}
995 		result = strstr(valuedup, mvaluedup) != 0;
996 		free(valuedup);
997 		free(mvaluedup);
998 		return result;
999 	} else if (operator == OP_EQUAL) {
1000 		return strcmp(value, mvalue) == 0;
1001 	} else {
1002 		return strcmp(value, mvalue) != 0;
1003 	}
1004 }
1005 
1006 static bool
match_rr_type(type_operator operator,char * value,char * mvalue)1007 match_rr_type(type_operator operator,
1008               char *value,
1009 	      char *mvalue)
1010 {
1011 	ldns_rr_type a,b;
1012 
1013 	a = ldns_get_rr_type_by_name(value);
1014 	b = ldns_get_rr_type_by_name(mvalue);
1015 
1016 	switch (operator) {
1017 		case OP_EQUAL:
1018 			return a == b;
1019 			break;
1020 		case OP_NOTEQUAL:
1021 			return a != b;
1022 			break;
1023 		case OP_GREATER:
1024 			return a > b;
1025 			break;
1026 		case OP_LESSER:
1027 			return a < b;
1028 			break;
1029 		case OP_GREATEREQUAL:
1030 			return a >= b;
1031 			break;
1032 		case OP_LESSEREQUAL:
1033 			return a <= b;
1034 			break;
1035 		default:
1036 			fprintf(stderr, "Unknown operator: %u\n", operator);
1037 			exit(2);
1038 	}
1039 }
1040 
1041 static bool
match_rcode(type_operator operator,char * value,char * mvalue)1042 match_rcode(type_operator operator,
1043              char *value,
1044              char *mvalue)
1045 {
1046 	int a, b;
1047 	int i;
1048 	ldns_lookup_table *lt;
1049 
1050 	/* try parse name first, then parse as int */
1051 	lt = ldns_lookup_by_name(ldns_rcodes, value);
1052 	if (lt) {
1053 		a = lt->id;
1054 	} else {
1055 		i = atoi(value);
1056 		if (i >= 0 && isdigit((unsigned char)value[0])) {
1057 			lt = ldns_lookup_by_id(ldns_rcodes, i);
1058 			if (lt) {
1059 				a = lt->id;
1060 			} else {
1061 				fprintf(stderr, "Unknown rcode: %s\n", value);
1062 				exit(1);
1063 				return false;
1064 			}
1065 		} else {
1066 			fprintf(stderr, "Unknown rcode: %s\n", value);
1067 			exit(1);
1068 			return false;
1069 		}
1070 	}
1071 
1072 	lt = ldns_lookup_by_name(ldns_rcodes, mvalue);
1073 	if (lt) {
1074 		b = lt->id;
1075 	} else {
1076 		i = atoi(mvalue);
1077 		if (i >= 0 && isdigit((unsigned char)mvalue[0])) {
1078 			lt = ldns_lookup_by_id(ldns_rcodes, i);
1079 			if (lt) {
1080 				b = lt->id;
1081 			} else {
1082 				fprintf(stderr, "Unknown rcode: %s\n", mvalue);
1083 				exit(1);
1084 				return false;
1085 			}
1086 		} else {
1087 			fprintf(stderr, "Unknown rcode: %s\n", mvalue);
1088 			exit(1);
1089 			return false;
1090 		}
1091 	}
1092 
1093 	switch(operator) {
1094 		case OP_EQUAL:
1095 			return a == b;
1096 			break;
1097 		case OP_NOTEQUAL:
1098 			return a != b;
1099 			break;
1100 		default:
1101 			fprintf(stderr, "Error bad operator for rcode: %s\n", get_op_str(operator));
1102 			return false;
1103 			break;
1104 	}
1105 }
1106 
1107 static bool
value_matches(match_id id,type_operator operator,char * value,char * mvalue)1108 value_matches(match_id id,
1109         type_operator operator,
1110         char *value,
1111         char *mvalue)
1112 {
1113 	int result;
1114 
1115 	if (verbosity >= 5) {
1116 		printf("Match %s: %s %s %s: ", get_match_name_str(id), value, get_op_str(operator), mvalue);
1117 	}
1118 	switch(id) {
1119 		case MATCH_OPCODE:
1120 			result = match_opcode(operator, value, mvalue);
1121 			break;
1122 		case MATCH_RCODE:
1123 			result = match_rcode(operator, value, mvalue);
1124 			break;
1125 		case MATCH_ID:
1126 		case MATCH_QR:
1127 		case MATCH_TC:
1128 		case MATCH_AD:
1129 		case MATCH_CD:
1130 		case MATCH_RD:
1131 		case MATCH_DO:
1132 		case MATCH_PACKETSIZE:
1133 		case MATCH_EDNS:
1134 		case MATCH_EDNS_PACKETSIZE:
1135 		case MATCH_QUESTION_SIZE:
1136 		case MATCH_ANSWER_SIZE:
1137 		case MATCH_AUTHORITY_SIZE:
1138 		case MATCH_ADDITIONAL_SIZE:
1139 		case MATCH_TIMESTAMP:
1140 			result = match_int(operator, value, mvalue);
1141 			break;
1142 		case MATCH_QUERY:
1143 		case MATCH_QNAME:
1144 		case MATCH_ANSWER:
1145 		case MATCH_AUTHORITY:
1146 		case MATCH_ADDITIONAL:
1147 			result = match_str(operator, value, mvalue);
1148 			break;
1149 		case MATCH_SRC_ADDRESS:
1150 		case MATCH_DST_ADDRESS:
1151 			result = match_str(operator, value, mvalue);
1152 			break;
1153 		case MATCH_QTYPE:
1154 			result = match_rr_type(operator, value, mvalue);
1155 			break;
1156 		default:
1157 			fprintf(stderr, "Error: value_matches() for operator %s not implemented yet.\n", get_op_str((type_operator) id));
1158 			exit(3);
1159 	}
1160 	if (verbosity >= 5) {
1161 		if (result) {
1162 			printf("true\n");
1163 		} else {
1164 			printf("false\n");
1165 		}
1166 	}
1167 	return result;
1168 }
1169 
1170 static char *
get_string_value(match_id id,ldns_pkt * pkt,ldns_rdf * src_addr,ldns_rdf * dst_addr)1171 get_string_value(match_id id, ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr)
1172 {
1173 	char *val;
1174 	match_table *mt;
1175 	size_t valsize = 100;
1176 
1177 	val = malloc(valsize);
1178 	memset(val, 0, valsize);
1179 
1180 	switch(id) {
1181 		case MATCH_QR:
1182 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_qr(pkt));
1183 			break;
1184 		case MATCH_ID:
1185 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_id(pkt));
1186 			break;
1187 		case MATCH_OPCODE:
1188 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_get_opcode(pkt));
1189 			break;
1190 		case MATCH_RCODE:
1191 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_get_rcode(pkt));
1192 			break;
1193 		case MATCH_PACKETSIZE:
1194 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_size(pkt));
1195 			break;
1196 		case MATCH_TC:
1197 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_tc(pkt));
1198 			break;
1199 		case MATCH_AD:
1200 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_ad(pkt));
1201 			break;
1202 		case MATCH_CD:
1203 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_cd(pkt));
1204 			break;
1205 		case MATCH_RD:
1206 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_rd(pkt));
1207 			break;
1208 		case MATCH_EDNS:
1209 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns(pkt));
1210 			break;
1211 		case MATCH_EDNS_PACKETSIZE:
1212 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_udp_size(pkt));
1213 			break;
1214 		case MATCH_DO:
1215 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_do(pkt));
1216 			break;
1217 		case MATCH_QUESTION_SIZE:
1218 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_qdcount(pkt));
1219 			break;
1220 		case MATCH_ANSWER_SIZE:
1221 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_ancount(pkt));
1222 			break;
1223 		case MATCH_AUTHORITY_SIZE:
1224 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_nscount(pkt));
1225 			break;
1226 		case MATCH_ADDITIONAL_SIZE:
1227 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_arcount(pkt));
1228 			break;
1229 		case MATCH_SRC_ADDRESS:
1230 			free(val);
1231 			val = ldns_rdf2str(src_addr);
1232 			break;
1233 		case MATCH_DST_ADDRESS:
1234 			free(val);
1235 			val = ldns_rdf2str(dst_addr);
1236 			break;
1237 		case MATCH_TIMESTAMP:
1238 			snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_timestamp(pkt).tv_sec);
1239 			break;
1240 		case MATCH_QUERY:
1241 			if (ldns_pkt_qdcount(pkt) > 0) {
1242 				free(val);
1243 				val = ldns_rr2str(ldns_rr_list_rr(ldns_pkt_question(pkt), 0));
1244 				/* replace \n for nicer printing later */
1245 				if (strchr(val, '\n')) {
1246 					*(strchr(val, '\n')) = '\0';
1247 				}
1248 			} else {
1249 				val[0] = '\0';
1250 			}
1251 			break;
1252 		case MATCH_QNAME:
1253 			if (ldns_pkt_qdcount(pkt) > 0) {
1254 				free(val);
1255 				val = ldns_rdf2str(ldns_rr_owner(ldns_rr_list_rr(ldns_pkt_question(pkt), 0)));
1256 				/* replace \n for nicer printing later */
1257 				if (strchr(val, '\n')) {
1258 					*(strchr(val, '\n')) = '\0';
1259 				}
1260 			} else {
1261 				val[0] = '\0';
1262 			}
1263 			break;
1264 		case MATCH_QTYPE:
1265 			if (ldns_pkt_qdcount(pkt) > 0) {
1266 				free(val);
1267 				val = ldns_rr_type2str(ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_question(pkt), 0)));
1268 			} else {
1269 				val[0] = '\0';
1270 			}
1271 			break;
1272 		case MATCH_ANSWER:
1273 			if (ldns_pkt_ancount(pkt) > 0) {
1274 				free(val);
1275 				val = ldns_rr_list2str(ldns_pkt_answer(pkt));
1276 			} else {
1277 				val[0] = '\0';
1278 			}
1279 			break;
1280 		case MATCH_AUTHORITY:
1281 			if (ldns_pkt_nscount(pkt) > 0) {
1282 				free(val);
1283 				val = ldns_rr_list2str(ldns_pkt_authority(pkt));
1284 			} else {
1285 				val[0] = '\0';
1286 			}
1287 			break;
1288 		case MATCH_ADDITIONAL:
1289 			if (ldns_pkt_arcount(pkt) > 0) {
1290 				free(val);
1291 				val = ldns_rr_list2str(ldns_pkt_additional(pkt));
1292 			} else {
1293 				val[0] = '\0';
1294 			}
1295 			break;
1296 		default:
1297 			mt = get_match_by_id(id);
1298 			if (!mt) {
1299 				printf("ERROR UNKNOWN MATCH_TABLE ID %u\n", id);
1300 				exit(1);
1301 			}
1302 			printf("Matcher for %s not implemented yet\n", mt->name);
1303 			exit(1);
1304 			return NULL;
1305 	}
1306 
1307 	return val;
1308 }
1309 
1310 static bool
match_packet_to_operation(ldns_pkt * pkt,ldns_rdf * src_addr,ldns_rdf * dst_addr,match_operation * operation)1311 match_packet_to_operation(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_operation *operation)
1312 {
1313 	bool result;
1314 	char *val;
1315 
1316 	if (!pkt || !operation) {
1317 		return false;
1318 	} else {
1319 		val = get_string_value(operation->id, pkt, src_addr, dst_addr);
1320 		if (!val) {
1321 			return false;
1322 		}
1323 		result = value_matches(operation->id, operation->operator, val, operation->value);
1324 		free(val);
1325 		return result;
1326 	}
1327 }
1328 
1329 static int
match_operation_compare(const void * a,const void * b)1330 match_operation_compare(const void *a, const void *b)
1331 {
1332 	match_operation *moa, *mob;
1333 	match_table *mt;
1334 	long ia, ib;
1335 
1336 	if (!a) {
1337 		return 1;
1338 	} else if (!b) {
1339 		return -1;
1340 	} else {
1341 		moa = (match_operation *) a;
1342 		mob = (match_operation *) b;
1343 
1344 		if (moa->id < mob->id) {
1345 			return -1;
1346 		} else if (moa->id > mob->id) {
1347 			return 1;
1348 		} else {
1349 			if (moa->operator < mob->operator) {
1350 				return -1;
1351 			} else if (moa->operator > mob->operator) {
1352 				return 1;
1353 			} else {
1354 				mt = get_match_by_id(moa->id);
1355 				if (mt) {
1356 					switch (mt->type) {
1357 						case TYPE_INT:
1358 						case TYPE_TIMESTAMP:
1359 						case TYPE_BOOL:
1360 						case TYPE_OPCODE:
1361 						case TYPE_RCODE:
1362 							ia = atol(moa->value);
1363 							ib = atol(mob->value);
1364 							return ia - ib;
1365 							break;
1366 						case TYPE_STRING:
1367 						case TYPE_ADDRESS:
1368 						case TYPE_RR:
1369 						default:
1370 							return strcmp(moa->value, mob->value);
1371 							break;
1372 					}
1373 				} else {
1374 					return strcmp(moa->value, mob->value);
1375 				}
1376 			}
1377 		}
1378 	}
1379 }
1380 
1381 static int
match_expression_compare(const void * a,const void * b)1382 match_expression_compare(const void *a, const void *b)
1383 {
1384 	match_expression *mea, *meb;
1385 
1386 	if (!a) {
1387 		return 1;
1388 	} else if (!b) {
1389 		return -1;
1390 	} else {
1391 		mea = (match_expression *) a;
1392 		meb = (match_expression *) b;
1393 
1394 		if (mea->op < meb->op) {
1395 			return -1;
1396 		} else if (mea->op > meb->op) {
1397 			return 1;
1398 		} else {
1399 			switch(mea->op) {
1400 				case MATCH_EXPR_AND:
1401 				case MATCH_EXPR_OR:
1402 					if (match_expression_compare(mea->left, meb->left) < 0) {
1403 						return -1;
1404 					} else if (match_expression_compare(mea->left, meb->left) > 0) {
1405 						return 1;
1406 					} else {
1407 						return match_expression_compare(mea->right, meb->right);
1408 					}
1409 					break;
1410 				case MATCH_EXPR_LEAF:
1411 					return match_operation_compare(mea->match, meb->match);
1412 					break;
1413 				default:
1414 					fprintf(stderr, "Unknown Match Expression logic operator: %u\n", mea->op);
1415 					exit(1);
1416 			}
1417 		}
1418 	}
1419 }
1420 
1421 /**
1422  * If count is true, and the counter is found, its count is increased by 1
1423  */
1424 static int
add_match_counter(match_counters * counters,match_expression * expr,bool count)1425 add_match_counter(match_counters *counters,
1426 		  match_expression *expr,
1427                   bool count)
1428 {
1429 	int cmp;
1430 	match_counters *new;
1431 
1432 	if (!counters || !expr) {
1433 		return -1;
1434 	} else {
1435 		if (counters->match) {
1436 			cmp = match_expression_compare(counters->match,
1437 			                               expr);
1438 			if (cmp > 0) {
1439 				if (counters->left) {
1440 					return add_match_counter(counters->left,
1441 					                         expr,
1442 					                         count);
1443 				} else {
1444 					new = malloc(sizeof(match_counters));
1445 					new->left = NULL;
1446 					new->right = NULL;
1447 					new->match = expr;
1448 					counters->left = new;
1449 					return 0;
1450 				}
1451 			} else if (cmp < 0) {
1452 				if (counters->right) {
1453 					return add_match_counter(counters->right,
1454 					                         expr,
1455 					                         count);
1456 				} else {
1457 					new = malloc(sizeof(match_counters));
1458 					new->left = NULL;
1459 					new->right = NULL;
1460 					new->match = expr;
1461 					counters->right = new;
1462 					return 0;
1463 				}
1464 			} else  {
1465 				/* already there? */
1466 				if (count) {
1467 					counters->match->count++;
1468 				}
1469 				return 1;
1470 			}
1471 		} else {
1472 			/* shouldn't happen but anyway */
1473 			counters->match = expr;
1474 		}
1475 	}
1476 	return 0;
1477 }
1478 
1479 static bool
match_dns_packet_to_expr(ldns_pkt * pkt,ldns_rdf * src_addr,ldns_rdf * dst_addr,match_expression * expr)1480 match_dns_packet_to_expr(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_expression *expr)
1481 {
1482 	bool result;
1483 
1484 	if (!pkt || !expr) {
1485 		return false;
1486 	}
1487 
1488 	switch(expr->op) {
1489 		case MATCH_EXPR_OR:
1490 			result = (match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->left) ||
1491 			       match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->right));
1492 			break;
1493 		case MATCH_EXPR_AND:
1494 			result = (match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->left) &&
1495 			       match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->right));
1496 			break;
1497 		case MATCH_EXPR_LEAF:
1498 			result = match_packet_to_operation(pkt, src_addr, dst_addr, expr->match);
1499 			break;
1500 		default:
1501 			fprintf(stderr, "Error, unknown expression operator %u\n", expr->op);
1502 			fprintf(stderr, "full expression:\n");
1503 			print_match_expression(stderr, expr);
1504 			fprintf(stderr, "\n");
1505 			exit(1);
1506 	}
1507 
1508 	if (result) {
1509 		if (verbosity >= 5) {
1510 			printf("Found Match:\n");
1511 			print_match_expression(stdout, expr);
1512 			printf("\nCount now %u\n", (unsigned int) expr->count);
1513 		}
1514 		expr->count++;
1515 	}
1516 
1517 	return result;
1518 }
1519 
1520 static void
free_match_operation(match_operation * operation)1521 free_match_operation(match_operation *operation)
1522 {
1523 	if (operation) {
1524 		if (operation->value) {
1525 			free(operation->value);
1526 		}
1527 		free(operation);
1528 	}
1529 }
1530 
1531 static void
free_match_expression(match_expression * expr)1532 free_match_expression(match_expression *expr)
1533 {
1534 	if (expr) {
1535 		switch(expr->op) {
1536 			case MATCH_EXPR_OR:
1537 			case MATCH_EXPR_AND:
1538 				free_match_expression(expr->left);
1539 				free_match_expression(expr->right);
1540 				break;
1541 			case MATCH_EXPR_LEAF:
1542 				free_match_operation(expr->match);
1543 				break;
1544 		}
1545 		free(expr);
1546 	}
1547 }
1548 
1549 static void
free_counters(match_counters * counters)1550 free_counters(match_counters *counters)
1551 {
1552 	if (counters) {
1553 		if (counters->left) {
1554 			free_counters(counters->left);
1555 		}
1556 		if (counters->match) {
1557 			free_match_expression(counters->match);
1558 		}
1559 		if (counters->right) {
1560 			free_counters(counters->right);
1561 		}
1562 		free(counters);
1563 	}
1564 }
1565 
1566 static void
match_pkt_counters(ldns_pkt * pkt,ldns_rdf * src_addr,ldns_rdf * dst_addr,match_counters * counts)1567 match_pkt_counters(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_counters *counts)
1568 {
1569 	if (counts->left) {
1570 		match_pkt_counters(pkt, src_addr, dst_addr, counts->left);
1571 	}
1572 	if (counts->match) {
1573 		if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, counts->match)) {
1574 /*
1575 			counts->match->count++;
1576 */
1577 		}
1578 	}
1579 	if (counts->right) {
1580 		match_pkt_counters(pkt, src_addr, dst_addr, counts->right);
1581 	}
1582 }
1583 
1584 static void
match_pkt_uniques(ldns_pkt * pkt,ldns_rdf * src_addr,ldns_rdf * dst_addr,match_counters * uniques,match_id unique_ids[],size_t unique_id_count)1585 match_pkt_uniques(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_counters *uniques, match_id unique_ids[], size_t unique_id_count)
1586 {
1587 	match_expression *me;
1588 	size_t i;
1589 	match_operation *mo;
1590 	int add_result;
1591 
1592 	for (i = 0; i < unique_id_count; i++) {
1593 		mo = malloc(sizeof(match_operation));
1594 		mo->id = unique_ids[i];
1595 		mo->operator = OP_EQUAL;
1596 		mo->value = get_string_value(mo->id, pkt, src_addr, dst_addr);
1597 
1598 		me = malloc(sizeof(match_expression));
1599 		me->op = MATCH_EXPR_LEAF;
1600 		me->left = NULL;
1601 		me->right = NULL;
1602 		me->match = mo;
1603 		me->count = 1;
1604 
1605 		add_result = add_match_counter(uniques, me, true);
1606 		/* if result=1 it was already found, so delete new one */
1607 		if (add_result == 1) {
1608 			free_match_expression(me);
1609 		}
1610 	}
1611 
1612 #if 0
1613 	size_t i, j;
1614 	bool found;
1615 	match_expression *me;
1616 	match_operation *mo;
1617 
1618 	/* get the value, match uniques for that, if not match, add new */
1619 	/* all unique values should be MATCH_EXPR_LEAF */
1620 		found = false;
1621 		for (j = 0; j < uniques->size; j++) {
1622 			if (uniques->counter[j]->match->id == unique_ids[i]) {
1623 				if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, uniques->counter[j])) {
1624 					found = true;
1625 				}
1626 			}
1627 		}
1628 		if (!found) {
1629 			mo = malloc(sizeof(match_operation));
1630 			mo->id = unique_ids[i];
1631 			mo->operator = OP_EQUAL;
1632 			mo->value = get_string_value(mo->id, pkt, src_addr, dst_addr);
1633 
1634 			me = malloc(sizeof(match_expression));
1635 			me->match = mo;
1636 			me->op = MATCH_EXPR_LEAF;
1637 			me->left = NULL;
1638 			me->right = NULL;
1639 			me->count = 1;
1640 
1641 			add_counter(uniques, me);
1642 		}
1643 	}
1644 #endif
1645 }
1646 
1647 static match_expression *
parse_match_expression(char * string)1648 parse_match_expression(char *string)
1649 {
1650 	match_expression *expr;
1651 	size_t i,j;
1652 	size_t leftstart, leftend = 0;
1653 	char *left_str, *op = NULL, *val;
1654 	match_table *mt;
1655 	match_operation *mo = NULL;
1656 	const type_operators *tos;
1657 	match_expression *result;
1658 	ldns_lookup_table *lt = NULL;
1659 
1660 	/* remove whitespace */
1661 	char *str = calloc(1, strlen(string) + 1);
1662 
1663 	j = 0;
1664 	for (i = 0; i < strlen(string); i++) {
1665 		if(!isspace((unsigned char)string[i])) {
1666 			str[j] = string[i];
1667 			j++;
1668 		}
1669 	}
1670 	str[j] = '\0';
1671 
1672 	expr = malloc(sizeof(match_expression));
1673 	expr->left = NULL;
1674 	expr->right = NULL;
1675 	expr->match = NULL;
1676 	expr->count = 0;
1677 	leftstart = 0;
1678 	for (i = 0; i < strlen(str); i++) {
1679 		if (str[i] == '&') {
1680 			expr->op = MATCH_EXPR_AND;
1681 			if (!expr->left) {
1682 				left_str = malloc(leftend - leftstart + 2);
1683 				strncpy(left_str, &str[leftstart], leftend-leftstart+1);
1684 				left_str[leftend - leftstart + 1] = '\0';
1685 				expr->left = parse_match_expression(left_str);
1686 				free(left_str);
1687 			}
1688 			expr->right = parse_match_expression(&str[i+1]);
1689 			if (expr->left && expr->right) {
1690 				result = expr;
1691 				goto done;
1692 			} else {
1693 				result = NULL;
1694 				goto done;
1695 			}
1696 		} else if (str[i] == '|') {
1697 			expr->op = MATCH_EXPR_OR;
1698 			if (!expr->left) {
1699 				left_str = malloc(leftend - leftstart + 2);
1700 				strncpy(left_str, &str[leftstart], leftend-leftstart+1);
1701 				left_str[leftend - leftstart + 1] = '\0';
1702 				expr->left = parse_match_expression(left_str);
1703 				free(left_str);
1704 			}
1705 			expr->right = parse_match_expression(&str[i+1]);
1706 			expr->count = 0;
1707 			if (expr->left && expr->right) {
1708 				result = expr;
1709 				goto done;
1710 			} else {
1711 				result = NULL;
1712 				goto done;
1713 			}
1714 		} else if (str[i] == '(') {
1715 			leftstart = i + 1;
1716 			j = 1;
1717 			while (j > 0) {
1718 				i++;
1719 				if (i > strlen(str)) {
1720 					printf("parse error: no closing bracket: %s\n", str);
1721 					printf("                                 ");
1722 					for (j = 0; j < leftstart - 1; j++) {
1723 						printf(" ");
1724 					}
1725 					printf("^\n");
1726 					result = NULL;
1727 					goto done;
1728 				}
1729 				if (str[i] == ')') {
1730 					j--;
1731 				} else if (str[i] == '(') {
1732 					j++;
1733 				} else {
1734 				}
1735 			}
1736 			leftend = i-1;
1737 			left_str = malloc(leftend - leftstart + 1);
1738 			strncpy(left_str, &str[leftstart], leftend - leftstart + 1);
1739 			expr->left = parse_match_expression(left_str);
1740 			free(left_str);
1741 			if (i >= strlen(str)-1) {
1742 				result = expr->left;
1743 				free_match_expression(expr);
1744 				goto done;
1745 			}
1746 		} else if (str[i] == ')') {
1747 			printf("parse error: ) without (\n");
1748 			result = NULL;
1749 			goto done;
1750 		} else {
1751 			leftend = i;
1752 		}
1753 	}
1754 
1755 	/* no operators or hooks left, expr should be of the form
1756 	   <name><operator><value> now */
1757 	for (i = 0; i < strlen(str); i++) {
1758 		if (str[i] == '=' ||
1759 		    str[i] == '>' ||
1760 		    str[i] == '<' ||
1761 		    str[i] == '!' ||
1762 		    str[i] == '~'
1763 		   ) {
1764 		 	leftend = i-1;
1765 			op = malloc(3);
1766 			j = 0;
1767 			op[j] = str[i];
1768 			i++;
1769 			j++;
1770 
1771 			if (i > strlen(str)) {
1772 				printf("parse error no right hand side: %s\n", str);
1773 				result = NULL;
1774 				goto done;
1775 			}
1776 			if (str[i] == '=' ||
1777 			    str[i] == '>' ||
1778 			    str[i] == '<' ||
1779 			    str[i] == '!' ||
1780 			    str[i] == '~'
1781 			   ) {
1782 			   	op[j] = str[i];
1783 				i++;
1784 			   	j++;
1785 				if (i > strlen(str)) {
1786 					printf("parse error no right hand side: %s\n", str);
1787 					result = NULL;
1788 					if (op)
1789 						free(op);
1790 					goto done;
1791 				}
1792 			}
1793 			op[j] = '\0';
1794 			left_str = malloc(leftend - leftstart + 2);
1795 			strncpy(left_str, &str[leftstart], leftend - leftstart + 1);
1796 			left_str[leftend - leftstart + 1] = '\0';
1797 			mt = get_match_by_name(left_str);
1798 			if (!mt) {
1799 				printf("parse error: unknown match name: %s\n", left_str);
1800 				if (op)
1801 					free(op);
1802 				result = NULL;
1803 				goto done;
1804 			} else {
1805 				/* check if operator is allowed */
1806 				tos = get_type_operators(mt->type);
1807 				for (j = 0; j < tos->operator_count; j++) {
1808 					if (get_op_id(op) == tos->operators[j]) {
1809 						if (mo)
1810 							free(mo);
1811 						mo = malloc(sizeof(match_operation));
1812 						mo->id = mt->id;
1813 						mo->operator = get_op_id(op);
1814 						switch (mt->type) {
1815 							case TYPE_BOOL:
1816 								val = malloc(2);
1817 								if (strncmp(&str[i], "true", 5) == 0 ||
1818 								    strncmp(&str[i], "TRUE", 5) == 0 ||
1819 								    strncmp(&str[i], "True", 5) == 0 ||
1820 								    strncmp(&str[i], "1", 2) == 0
1821 								) {
1822 									val[0] = '1';
1823 									val[1] = '\0';
1824 								} else if (strncmp(&str[i], "false", 5) == 0 ||
1825 								    strncmp(&str[i], "FALSE", 5) == 0 ||
1826 								    strncmp(&str[i], "False", 5) == 0 ||
1827 								    strncmp(&str[i], "0", 2) == 0
1828 								) {
1829 
1830 									val[0] = '0';
1831 								} else {
1832 									fprintf(stderr, "Bad value for bool: %s\n", &str[i]);
1833 									exit(EXIT_FAILURE);
1834 								}
1835 								val[1] = '\0';
1836 								break;
1837 							case TYPE_RR:
1838 								/* convert first so we have the same strings for the same rrs in match_ later */
1839 								/*
1840 								qrr = ldns_rr_new_frm_str(&str[i], LDNS_DEFAULT_TTL, NULL);
1841 								if (!qrr) {
1842 									fprintf(stderr, "Bad value for RR: %s\n", &str[i]);
1843 									exit(EXIT_FAILURE);
1844 								}
1845 								val = ldns_rr2str(qrr);
1846 								*/
1847 								/* remove \n for readability */
1848 								/*
1849 								if (strchr(val, '\n')) {
1850 									*(strchr(val, '\n')) = '\0';
1851 								}
1852 								ldns_rr_free(qrr);
1853 								*/
1854 								val = strdup(&str[i]);
1855 								break;
1856 							case TYPE_OPCODE:
1857 								lt = ldns_lookup_by_name(ldns_opcodes, &str[i]);
1858 								if (lt) {
1859 									val = malloc(4);
1860 									snprintf(val, 3, "%u", (unsigned int) lt->id);
1861 								} else {
1862 									val = strdup(&str[i]);
1863 								}
1864 								break;
1865 							case TYPE_RCODE:
1866 								lt = ldns_lookup_by_name(ldns_rcodes, &str[i]);
1867 								if (lt) {
1868 									val = malloc(4);
1869 									snprintf(val, 3, "%u", (unsigned int) lt->id);
1870 								} else {
1871 									val = strdup(&str[i]);
1872 								}
1873 								break;
1874 							default:
1875 								val = strdup(&str[i]);
1876 								break;
1877 						}
1878 						mo->value = val;
1879 					}
1880 				}
1881 				if (!mo) {
1882 					printf("parse error: operator %s not allowed for match %s\n", op, left_str);
1883 					result = NULL;
1884 					if (op)
1885 						free(op);
1886 					goto done;
1887 				}
1888 			}
1889 			free(left_str);
1890 			free(op);
1891 			expr->match = mo;
1892 			expr->op = MATCH_EXPR_LEAF;
1893 			result = expr;
1894 			goto done;
1895 		}
1896 	}
1897 
1898 	result = NULL;
1899 
1900 	done:
1901 	free(str);
1902 	if (!result) {
1903 		free_match_expression(expr);
1904 	}
1905 	return result;
1906 
1907 }
1908 /* end of matches and counts */
1909 void
usage(FILE * output)1910 usage(FILE *output)
1911 {
1912 	fprintf(output, "Usage: ldns-dpa [OPTIONS] <pcap file>\n");
1913 	fprintf(output, "Options:\n");
1914 	fprintf(output, "\t-c <exprlist>:\tCount occurrences of matching expressions\n");
1915 	fprintf(output, "\t-f <expression>:\tFilter occurrences of matching expressions\n");
1916 	fprintf(output, "\t-h:\t\tshow this help\n");
1917 	fprintf(output, "\t-p:\t\tshow percentage of -u and -c values (of the total of\n\t\t\tmatching on the -f filter. if no filter is given,\n\t\t\tpercentages are on all correct dns packets)\n");
1918 	fprintf(output, "\t-of <file>:\tWrite pcap packets that match the -f flag to file\n");
1919 	fprintf(output, "\t-ofh <file>:\tWrite pcap packets that match the -f flag to file\n\t\tin a hexadecimal format readable by drill\n");
1920 	fprintf(output, "\t-s:\t\tshow possible match names\n");
1921 	fprintf(output, "\t-s <matchname>:\tshow possible match operators and values for <name>\n");
1922 	fprintf(output, "\t-sf:\t\tPrint packet that match -f. If no -f is given, print\n\t\t\tall dns packets\n");
1923 	fprintf(output, "\t-u <matchnamelist>:\tCount all occurrences of matchname\n");
1924 	fprintf(output, "\t-ua:\t\tShow average value of every -u matchname\n");
1925 	fprintf(output, "\t-uac:\t\tShow average count of every -u matchname\n");
1926 	fprintf(output, "\t-um <number>:\tOnly show -u results that occurred more than number times\n");
1927 	fprintf(output, "\t-v <level>:\tbe more verbose\n");
1928 	fprintf(output, "\t-notip <file>:\tDump pcap packets that were not recognized as\n\t\t\tIP packets to file\n");
1929 	fprintf(output, "\t-baddns <file>:\tDump mangled dns packets to file\n");
1930 	fprintf(output, "\t-version:\tShow the version and exit\n");
1931 	fprintf(output, "\n");
1932 	fprintf(output, "The filename '-' stands for stdin or stdout, so you can use \"-of -\" if you want to pipe the output to another process\n");
1933 	fprintf(output, "\n");
1934 	fprintf(output, "A <list> is a comma separated list of items\n");
1935 	fprintf(output, "\n");
1936 	fprintf(output, "An expression has the following form:\n");
1937 	fprintf(output, "<expr>:\t(<expr>)\n");
1938 	fprintf(output, "\t<expr> | <expr>\n");
1939 	fprintf(output, "\t<expr> & <expr>\n");
1940 	fprintf(output, "\t<match>\n");
1941 	fprintf(output, "\n");
1942 	fprintf(output, "<match>:\t<matchname> <operator> <value>\n");
1943 	fprintf(output, "\n");
1944 	fprintf(output, "See the -s option for possible matchnames, operators and values.\n");
1945 }
1946 
1947 void
show_match_names(char * name)1948 show_match_names(char *name)
1949 {
1950 	size_t j;
1951 	match_table *mt;
1952 	ldns_lookup_table *lt;
1953 	const type_operators *tos;
1954 	char *str;
1955 	size_t i;
1956 
1957 	if (name) {
1958 		mt = get_match_by_name(name);
1959 		if (mt) {
1960 			printf("%s:\n", mt->name);
1961 			printf("\t%s.\n", mt->description);
1962 			printf("\toperators: ");
1963 			printf("\t");
1964 			tos = get_type_operators(mt->type);
1965 			if (tos)  {
1966 				for (j = 0; j < tos->operator_count; j++) {
1967 					printf("%s ", get_op_str(tos->operators[j]));
1968 /*
1969 					lt = ldns_lookup_by_id((ldns_lookup_table *) lt_operators, tos->operators[j]);
1970 					if (lt) {
1971 						printf("%s ", lt->name);
1972 					} else {
1973 						printf("? ");
1974 					}
1975 */
1976 				}
1977 			} else {
1978 				printf("unknown type");
1979 			}
1980 
1981 			printf("\n");
1982 			printf("\tValues:\n");
1983 			switch (mt->type) {
1984 				case TYPE_INT:
1985 					printf("\t\t<Integer>\n");
1986 					break;
1987 				case TYPE_BOOL:
1988 					printf("\t\t0\n");
1989 					printf("\t\t1\n");
1990 					printf("\t\ttrue\n");
1991 					printf("\t\tfalse\n");
1992 					break;
1993 				case TYPE_OPCODE:
1994 					printf("\t\t<Integer>\n");
1995 					lt = ldns_opcodes;
1996 					while (lt->name != NULL) {
1997 						printf("\t\t%s\n", lt->name);
1998 						lt++;
1999 					}
2000 					break;
2001 				case TYPE_RCODE:
2002 					printf("\t\t<Integer>\n");
2003 					lt = ldns_rcodes;
2004 					while (lt->name != NULL) {
2005 						printf("\t\t%s\n", lt->name);
2006 						lt++;
2007 					}
2008 					break;
2009 				case TYPE_STRING:
2010 					printf("\t\t<String>\n");
2011 					break;
2012 				case TYPE_TIMESTAMP:
2013 					printf("\t\t<Integer> (seconds since epoch)\n");
2014 					break;
2015 				case TYPE_ADDRESS:
2016 					printf("\t\t<IP address>\n");
2017 					break;
2018 				case TYPE_RR:
2019 					printf("\t\t<Resource Record>\n");
2020 					break;
2021 				default:
2022 					break;
2023 			}
2024 		} else {
2025 			printf("Unknown match name: %s\n", name);
2026 		}
2027 	} else {
2028 		mt = (match_table *) matches;
2029 		while (mt->name != NULL) {
2030 			str = (char *) mt->name;
2031 			printf("%s:", str);
2032 			i = strlen(str) + 1;
2033 			while (i < 24) {
2034 				printf(" ");
2035 				i++;
2036 			}
2037 			printf("%s\n", mt->description);
2038 			mt++;
2039 		}
2040 	}
2041 }
2042 
2043 int
handle_ether_packet(const u_char * data,struct pcap_pkthdr cur_hdr,match_counters * count,match_expression * match_expr,match_counters * uniques,match_id unique_ids[],size_t unique_id_count)2044 handle_ether_packet(const u_char *data, struct pcap_pkthdr cur_hdr, match_counters *count, match_expression *match_expr, match_counters *uniques, match_id unique_ids[], size_t unique_id_count)
2045 {
2046 	struct ether_header *eptr;
2047 	struct ip *iptr;
2048 	struct ip6_hdr *ip6_hdr;
2049 	int ip_hdr_size;
2050 	uint8_t protocol;
2051 	size_t data_offset = 0;
2052 	ldns_rdf *src_addr = NULL, *dst_addr = NULL;
2053 	uint8_t *ap;
2054 	char *astr;
2055 	bpf_u_int32 len = cur_hdr.caplen;
2056 	struct timeval timestamp;
2057 	uint16_t ip_flags;
2058 	uint16_t ip_len;
2059 	uint16_t ip_id;
2060 	uint16_t ip_f_offset;
2061 	const u_char *newdata = NULL;
2062 /*
2063 printf("timeval: %u ; %u\n", cur_hdr.ts.tv_sec, cur_hdr.ts.tv_usec);
2064 */
2065 
2066 	uint8_t *dnspkt;
2067 
2068 	ldns_pkt *pkt;
2069 	ldns_status status;
2070 
2071 	/* lets start with the ether header... */
2072 	eptr = (struct ether_header *) data;
2073 	/* Do a couple of checks to see what packet type we have..*/
2074 	if (ntohs (eptr->ether_type) == ETHERTYPE_IP)
2075 	{
2076 		if (verbosity >= 5) {
2077 			printf("Ethernet type hex:%x dec:%u is an IP packet\n",
2078 				(unsigned int) ntohs(eptr->ether_type),
2079 				(unsigned int) ntohs(eptr->ether_type));
2080 		}
2081 
2082 		data_offset = ETHER_HEADER_LENGTH;
2083 		iptr = (struct ip *) (data + data_offset);
2084 		/*
2085 		printf("IP_OFF: %u (%04x) %04x %04x (%d) (%d)\n", iptr->ip_off, iptr->ip_off, IP_MF, IP_DF, iptr->ip_off & 0x4000, iptr->ip_off & 0x2000);
2086 		*/
2087 		ip_flags = ldns_read_uint16(&(iptr->ip_off));
2088 		ip_id = ldns_read_uint16(&(iptr->ip_id));
2089 		ip_len = ldns_read_uint16(&(iptr->ip_len));
2090 		ip_f_offset = (ip_flags & IP_OFFMASK)*8;
2091 		if (ip_flags & IP_MF && ip_f_offset == 0) {
2092 			/*printf("First Frag id %u len\n", ip_id, ip_len);*/
2093 			fragment_p->ip_id = ip_id;
2094 			memset(fragment_p->data, 0, 65535);
2095 			memcpy(fragment_p->data, iptr, ip_len);
2096 			fragment_p->cur_len = ip_len + 20;
2097 /*
2098 				for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) {
2099 					if (ip_len > 0 && ip_len % 20 == 0) {
2100 						printf("\t; %u - %u\n", ip_len - 19, ip_len);
2101 					}
2102 					printf("%02x ", fragment_p->data[ip_len]);
2103 				}
2104 				printf("\t; ??? - %u\n", ip_len);
2105 */
2106 			return 0;
2107 		} else
2108 		if (ip_flags & IP_MF && ip_f_offset != 0) {
2109 			/*printf("Next frag\n");*/
2110 			if (ip_id == fragment_p->ip_id) {
2111 				/*printf("add fragment to current id %u len %u offset %u\n", ip_id, ip_len, ip_f_offset);*/
2112 				memcpy(fragment_p->data + (ip_f_offset) + 20, data+data_offset+20, ip_len - (iptr->ip_hl)*4);
2113 				/*printf("COPIED %u\n", ip_len);*/
2114 				fragment_p->cur_len = fragment_p->cur_len + ip_len - 20;
2115 				/*printf("cur len now %u\n", fragment_p->cur_len);*/
2116 /*
2117 				for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) {
2118 					if (ip_len > 0 && ip_len % 20 == 0) {
2119 						printf("\t; %u - %u\n", ip_len - 19, ip_len);
2120 					}
2121 					printf("%02x ", fragment_p->data[ip_len]);
2122 				}
2123 				printf("\t; ??? - %u\n", ip_len);
2124 */
2125 				return 0;
2126 			} else {
2127 				/*printf("Lost fragment %u\n", iptr->ip_id);*/
2128 				lost_packet_fragments++;
2129 				return 1;
2130 			}
2131 		} else
2132 		if (!(ip_flags & IP_MF) && ip_f_offset != 0) {
2133 			/*printf("Last frag\n");*/
2134 			if (ip_id == fragment_p->ip_id) {
2135 				/*printf("add fragment to current id %u len %u offset %u\n", ip_id, ip_len, ip_f_offset);*/
2136 				memcpy(fragment_p->data + ip_f_offset + 20, data+data_offset+20, ip_len - 20);
2137 				fragment_p->cur_len = fragment_p->cur_len + ip_len - 20;
2138 				iptr = (struct ip *) fragment_p->data;
2139 				newdata = malloc(fragment_p->cur_len + data_offset);
2140 				if (!newdata) {
2141 					printf("Malloc failed, out of mem?\n");
2142 					exit(4);
2143 				}
2144 				memcpy((char *) newdata, data, data_offset);
2145 				memcpy((char *) newdata+data_offset, fragment_p->data, fragment_p->cur_len);
2146 				iptr->ip_len = (u_short) ldns_read_uint16(&(fragment_p->cur_len));
2147 				iptr->ip_off = 0;
2148 				len = (bpf_u_int32) fragment_p->cur_len;
2149 				cur_hdr.caplen = len;
2150 				fragment_p->ip_id = 0;
2151 				fragmented_packets++;
2152 /*
2153 				for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) {
2154 					if (ip_len > 0 && ip_len % 20 == 0) {
2155 						printf("\t; %u - %u\n", ip_len - 19, ip_len);
2156 					}
2157 					printf("%02x ", fragment_p->data[ip_len]);
2158 				}
2159 				printf("\t; ??? - %u\n", ip_len);
2160 */
2161 			} else {
2162 				/*printf("Lost fragment %u\n", iptr->ip_id);*/
2163 				lost_packet_fragments++;
2164 				return 1;
2165 			}
2166 		} else {
2167 			newdata = data;
2168 		}
2169 /*
2170 		if (iptr->ip_off & 0x0040) {
2171 			printf("Don't fragment\n");
2172 		}
2173 */
2174 
2175 			/* in_addr portability woes, going manual for now */
2176 			/* ipv4 */
2177 			ap = (uint8_t *) &(iptr->ip_src);
2178 			astr = malloc(INET_ADDRSTRLEN);
2179 			if (inet_ntop(AF_INET, ap, astr, INET_ADDRSTRLEN)) {
2180 				if (ldns_str2rdf_a(&src_addr, astr) == LDNS_STATUS_OK) {
2181 
2182 				}
2183 			}
2184 			free(astr);
2185 			ap = (uint8_t *) &(iptr->ip_dst);
2186 			astr = malloc(INET_ADDRSTRLEN);
2187 			if (inet_ntop(AF_INET, ap, astr, INET_ADDRSTRLEN)) {
2188 				if (ldns_str2rdf_a(&dst_addr, astr) == LDNS_STATUS_OK) {
2189 
2190 				}
2191 			}
2192 			free(astr);
2193 
2194 			ip_hdr_size = (int) iptr->ip_hl * 4;
2195 			protocol = (uint8_t) iptr->ip_p;
2196 
2197 			data_offset += ip_hdr_size;
2198 
2199 			if (protocol == IPPROTO_UDP) {
2200 				udp_packets++;
2201 				data_offset += UDP_HEADER_LENGTH;
2202 
2203 				dnspkt = (uint8_t *) (newdata + data_offset);
2204 
2205 				/*printf("packet starts at byte %u\n", data_offset);*/
2206 
2207 				/*printf("Len: %u\n", len);*/
2208 
2209 				status = ldns_wire2pkt(&pkt, dnspkt, len - data_offset);
2210 
2211 				if (status != LDNS_STATUS_OK) {
2212 					if (verbosity >= 3) {
2213 						printf("No dns packet: %s\n", ldns_get_errorstr_by_id(status));
2214 					}
2215 					if (verbosity >= 5) {
2216 						for (ip_len = 0; ip_len < len - data_offset; ip_len++) {
2217 							if (ip_len > 0 && ip_len % 20 == 0) {
2218 								printf("\t; %u - %u\n", (unsigned int) ip_len - 19, (unsigned int) ip_len);
2219 							}
2220 							printf("%02x ", (unsigned int) dnspkt[ip_len]);
2221 						}
2222 						printf("\t; ??? - %u\n", (unsigned int) ip_len);
2223 
2224 					}
2225 					bad_dns_packets++;
2226 					if (bad_dns_dump) {
2227 						pcap_dump((u_char *)bad_dns_dump, &cur_hdr, newdata);
2228 					}
2229 				} else {
2230 					timestamp.tv_sec = cur_hdr.ts.tv_sec;
2231 					timestamp.tv_usec = cur_hdr.ts.tv_usec;
2232 					ldns_pkt_set_timestamp(pkt, timestamp);
2233 
2234 					if (verbosity >= 4) {
2235 						printf("DNS packet\n");
2236 						ldns_pkt_print(stdout, pkt);
2237 						printf("\n\n");
2238 					}
2239 
2240 					total_nr_of_dns_packets++;
2241 
2242 					if (match_expr) {
2243 						if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, match_expr)) {
2244 							/* if outputfile write */
2245 							if (dumper) {
2246 								pcap_dump((u_char *)dumper, &cur_hdr, data);
2247 							}
2248 							if (hexdumpfile) {
2249 								fprintf(hexdumpfile, ";; %u\n", (unsigned int) total_nr_of_dns_packets);
2250 								ldns_pkt2file_hex(hexdumpfile, pkt);
2251 							}
2252 							if (show_filter_matches) {
2253 								printf(";; From: ");
2254 								ldns_rdf_print(stdout, src_addr);
2255 								printf("\n");
2256 								printf(";; To:   ");
2257 								ldns_rdf_print(stdout, dst_addr);
2258 								printf("\n");
2259 								ldns_pkt_print(stdout, pkt);
2260 								printf("------------------------------------------------------------\n\n");
2261 							}
2262 						} else {
2263 							ldns_pkt_free(pkt);
2264 							ldns_rdf_deep_free(src_addr);
2265 							ldns_rdf_deep_free(dst_addr);
2266 							if (newdata && newdata != data)
2267 								free((void *)newdata);
2268 							return 0;
2269 						}
2270 					} else {
2271 						if (dumper) {
2272 							pcap_dump((u_char *)dumper, &cur_hdr, data);
2273 						}
2274 						if (hexdumpfile) {
2275 							fprintf(hexdumpfile, ";; %u\n", (unsigned int) total_nr_of_dns_packets);
2276 							ldns_pkt2file_hex(hexdumpfile, pkt);
2277 						}
2278 						if (show_filter_matches) {
2279 							printf(";; From: ");
2280 							ldns_rdf_print(stdout, src_addr);
2281 							printf("\n");
2282 							printf(";; To:   ");
2283 							ldns_rdf_print(stdout, dst_addr);
2284 							printf("\n");
2285 							ldns_pkt_print(stdout, pkt);
2286 							printf("------------------------------------------------------------\n\n");
2287 						}
2288 					}
2289 
2290 					/* General counters here */
2291 					total_nr_of_filtered_packets++;
2292 
2293 					match_pkt_counters(pkt, src_addr, dst_addr, count);
2294 					match_pkt_uniques(pkt, src_addr, dst_addr, uniques, unique_ids, unique_id_count);
2295 
2296 					ldns_pkt_free(pkt);
2297 					pkt = NULL;
2298 				}
2299 				ldns_rdf_deep_free(src_addr);
2300 				ldns_rdf_deep_free(dst_addr);
2301 
2302 			} else if (protocol == IPPROTO_TCP) {
2303 				/* tcp packets are skipped */
2304 				tcp_packets++;
2305 			}
2306 			if (newdata && newdata != data) {
2307 				free((void *)newdata);
2308 				newdata = NULL;
2309 			}
2310 	/* don't have a define for ethertype ipv6 */
2311 	} else 	if (ntohs (eptr->ether_type) == ETHERTYPE_IPV6) {
2312 		/*printf("IPv6!\n");*/
2313 
2314 
2315 		/* copied from ipv4, move this to function? */
2316 
2317 		data_offset = ETHER_HEADER_LENGTH;
2318 		ip6_hdr = (struct ip6_hdr *) (data + data_offset);
2319 
2320 		newdata = data;
2321 
2322 		/* in_addr portability woes, going manual for now */
2323 		/* ipv6 */
2324 		ap = (uint8_t *) &(ip6_hdr->ip6_src);
2325 		astr = malloc(INET6_ADDRSTRLEN);
2326 		if (inet_ntop(AF_INET6, ap, astr, INET6_ADDRSTRLEN)) {
2327 			if (ldns_str2rdf_aaaa(&src_addr, astr) == LDNS_STATUS_OK) {
2328 
2329 			}
2330 		}
2331 		free(astr);
2332 		ap = (uint8_t *) &(ip6_hdr->ip6_dst);
2333 		astr = malloc(INET6_ADDRSTRLEN);
2334 		if (inet_ntop(AF_INET6, ap, astr, INET6_ADDRSTRLEN)) {
2335 			if (ldns_str2rdf_aaaa(&dst_addr, astr) == LDNS_STATUS_OK) {
2336 
2337 			}
2338 		}
2339 		free(astr);
2340 
2341 		ip_hdr_size = IP6_HEADER_LENGTH;
2342 		protocol = (uint8_t) ip6_hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt;
2343 
2344 		data_offset += ip_hdr_size;
2345 
2346 		if (protocol == IPPROTO_UDP) {
2347 			udp_packets++;
2348 			/*printf("V6 UDP!\n");*/
2349 			data_offset += UDP_HEADER_LENGTH;
2350 
2351 			dnspkt = (uint8_t *) (newdata + data_offset);
2352 
2353 			/*printf("Len: %u\n", len);*/
2354 
2355 			status = ldns_wire2pkt(&pkt, dnspkt, len - data_offset);
2356 
2357 			if (status != LDNS_STATUS_OK) {
2358 				if (verbosity >= 3) {
2359 					printf("No dns packet: %s\n", ldns_get_errorstr_by_id(status));
2360 				}
2361 				bad_dns_packets++;
2362 				if (bad_dns_dump) {
2363 					pcap_dump((u_char *)bad_dns_dump, &cur_hdr, newdata);
2364 				}
2365 			} else {
2366 				timestamp.tv_sec = cur_hdr.ts.tv_sec;
2367 				timestamp.tv_usec = cur_hdr.ts.tv_usec;
2368 				ldns_pkt_set_timestamp(pkt, timestamp);
2369 
2370 				if (verbosity >= 4) {
2371 					printf("DNS packet\n");
2372 					ldns_pkt_print(stdout, pkt);
2373 					printf("\n\n");
2374 				}
2375 
2376 				total_nr_of_dns_packets++;
2377 
2378 				if (match_expr) {
2379 					if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, match_expr)) {
2380 						/* if outputfile write */
2381 						if (dumper) {
2382 							pcap_dump((u_char *)dumper, &cur_hdr, data);
2383 						}
2384 						if (show_filter_matches) {
2385 							printf(";; From: ");
2386 							ldns_rdf_print(stdout, src_addr);
2387 							printf("\n");
2388 							printf(";; To:   ");
2389 							ldns_rdf_print(stdout, dst_addr);
2390 							printf("\n");
2391 							ldns_pkt_print(stdout, pkt);
2392 							printf("------------------------------------------------------------\n\n");
2393 						}
2394 					} else {
2395 						ldns_pkt_free(pkt);
2396 						ldns_rdf_deep_free(src_addr);
2397 						ldns_rdf_deep_free(dst_addr);
2398 						return 0;
2399 					}
2400 				} else {
2401 					if (show_filter_matches) {
2402 						printf(";; From: ");
2403 						ldns_rdf_print(stdout, src_addr);
2404 						printf("\n");
2405 						printf(";; To:   ");
2406 						ldns_rdf_print(stdout, dst_addr);
2407 						printf("\n");
2408 						ldns_pkt_print(stdout, pkt);
2409 						printf("------------------------------------------------------------\n\n");
2410 					}
2411 				}
2412 
2413 				/* General counters here */
2414 				total_nr_of_filtered_packets++;
2415 
2416 				match_pkt_counters(pkt, src_addr, dst_addr, count);
2417 				match_pkt_uniques(pkt, src_addr, dst_addr, uniques, unique_ids, unique_id_count);
2418 
2419 				ldns_pkt_free(pkt);
2420 				pkt = NULL;
2421 			}
2422 			ldns_rdf_deep_free(src_addr);
2423 			ldns_rdf_deep_free(dst_addr);
2424 
2425 		} else if (protocol == IPPROTO_TCP) {
2426 			/* tcp packets are skipped */
2427 			tcp_packets++;
2428 		} else {
2429 			printf("ipv6 unknown next header type: %u\n", (unsigned int) protocol);
2430 		}
2431 
2432 
2433 
2434 	} else  if (ntohs (eptr->ether_type) == ETHERTYPE_ARP) {
2435 		if (verbosity >= 5) {
2436 			printf("Ethernet type hex:%x dec:%u is an ARP packet\n",
2437 				(unsigned int) ntohs(eptr->ether_type),
2438 				(unsigned int) ntohs(eptr->ether_type));
2439 		}
2440 		arp_packets++;
2441 	} else {
2442 		printf("Ethernet type %x not IP\n", (unsigned int) ntohs(eptr->ether_type));
2443 		if (verbosity >= 5) {
2444 			printf("Ethernet type %x not IP\n", (unsigned int) ntohs(eptr->ether_type));
2445 		}
2446 		not_ip_packets++;
2447 		if (not_ip_dump) {
2448 			pcap_dump((u_char *)not_ip_dump, &cur_hdr, data);
2449 		}
2450 	}
2451 
2452 	return 0;
2453 }
2454 
2455 bool
parse_match_list(match_counters * counters,char * string)2456 parse_match_list(match_counters *counters, char *string)
2457 {
2458 	size_t i;
2459 	match_expression *expr;
2460 /*	match_counter *mc;*/
2461 	size_t lastpos = 0;
2462 	char *substring;
2463 
2464 	/*printf("Parsing match list: '%s'\n", string);*/
2465 
2466 	for (i = 0; i < strlen(string); i++) {
2467 		if (string[i] == ',') {
2468 			if (i<2) {
2469 				fprintf(stderr, "Matchlist cannot start with ,\n");
2470 				return false;
2471 			} else {
2472 				substring = malloc(strlen(string)+1);
2473 				strncpy(substring, &string[lastpos], i - lastpos + 1);
2474 				substring[i - lastpos] = '\0';
2475 				expr = parse_match_expression(substring);
2476 				free(substring);
2477 				if (!expr) {
2478 					return false;
2479 				}
2480 				/*
2481 				if (expr->op != MATCH_EXPR_LEAF) {
2482 					fprintf(stderr, "Matchlist can only contain <match>, not a logic expression\n");
2483 					return false;
2484 				}
2485 				*/
2486 				add_match_counter(counters, expr, false);
2487 				lastpos = i+1;
2488 			}
2489 		}
2490 	}
2491 	substring = malloc(strlen(string) + 1);
2492 	strncpy(substring, &string[lastpos], i - lastpos + 1);
2493 	substring[i - lastpos] = '\0';
2494 	expr = parse_match_expression(substring);
2495 
2496 	if (!expr) {
2497 		fprintf(stderr, "Bad match: %s\n", substring);
2498 		free(substring);
2499 		return false;
2500 	}
2501 	free(substring);
2502 	/*
2503 	if (expr->op != MATCH_EXPR_LEAF) {
2504 		fprintf(stderr, "Matchlist can only contain <match>, not a logic expression\n");
2505 		return false;
2506 	}
2507 	*/
2508 	add_match_counter(counters, expr, false);
2509 	return true;
2510 }
2511 
2512 bool
parse_uniques(match_id ids[],size_t * count,char * string)2513 parse_uniques(match_id ids[], size_t *count, char *string)
2514 {
2515 	size_t i, j, lastpos;
2516 	char *str, *strpart;
2517 	match_table *mt;
2518 
2519 	/*printf("Parsing unique counts: '%s'\n", string);*/
2520 	str = calloc(1, strlen(string) + 1);
2521 	j = 0;
2522 	for (i = 0; i < strlen(string); i++) {
2523 		if (!isspace((unsigned char)string[i])) {
2524 			str[j] = string[i];
2525 			j++;
2526 		}
2527 	}
2528 	str[j] = '\0';
2529 
2530 	lastpos = 0;
2531 	for (i = 0; i <= strlen(str); i++) {
2532 		if (str[i] == ',' || i >= strlen(str)) {
2533 			if (!(strpart = malloc(i - lastpos + 1))) {
2534 				free(str);
2535 				return false;
2536 			}
2537 			strncpy(strpart, &str[lastpos], i - lastpos);
2538 			strpart[i - lastpos] = '\0';
2539 			if ((mt = get_match_by_name(strpart))) {
2540 				ids[*count] = mt->id;
2541 				*count = *count + 1;
2542 			} else {
2543 				printf("Error parsing match list; unknown match name: %s\n", strpart);
2544 				free(strpart);
2545 				free(str);
2546 				return false;
2547 			}
2548 			free(strpart);
2549 			lastpos = i + 1;
2550 		}
2551 	}
2552 	if (i > lastpos) {
2553 		strpart = malloc(i - lastpos + 1);
2554 		strncpy(strpart, &str[lastpos], i - lastpos);
2555 		strpart[i - lastpos] = '\0';
2556 		if ((mt = get_match_by_name(strpart))) {
2557 			ids[*count] = mt->id;
2558 			*count = *count + 1;
2559 		} else {
2560 			printf("Error parsing match list; unknown match name: %s\n", strpart);
2561 			return false;
2562 		}
2563 		free(strpart);
2564 	}
2565 	free(str);
2566 	return true;
2567 }
2568 
main(int argc,char * argv[])2569 int main(int argc, char *argv[]) {
2570 
2571 	int i;
2572 	int status = EXIT_SUCCESS;
2573 	match_counters *count = malloc(sizeof(match_counters));
2574 	const char *inputfile = NULL;
2575 	char errbuf[PCAP_ERRBUF_SIZE];
2576 	pcap_t *pc = NULL;
2577 	const u_char *cur;
2578 	struct pcap_pkthdr cur_hdr;
2579 	match_expression *expr = NULL;
2580 	match_id unique_ids[MAX_MATCHES];
2581 	size_t unique_id_count = 0; /* number of unique counters */
2582 	match_counters *uniques = malloc(sizeof(match_counters));
2583 	char *dumpfile = NULL;
2584 	char *hexdumpfilename = NULL;
2585 	char *not_ip_dumpfile = NULL;
2586 	char *bad_dns_dumpfile = NULL;
2587 
2588 	bool show_percentages = false;
2589 	bool show_averages = false;
2590 	bool show_average_count = false;
2591 	int unique_minimum = 0;
2592 
2593 	count->left = NULL;
2594 	count->match = NULL;
2595 	count->right = NULL;
2596 	uniques->left = NULL;
2597 	uniques->match = NULL;
2598 	uniques->right = NULL;
2599 
2600 	fragment_p = malloc(sizeof(struct fragment_part));
2601 	fragment_p->ip_id = 0;
2602 	fragment_p->cur_len = 0;
2603 
2604 	for (i = 1; i < argc; i++) {
2605 
2606 		if (strncmp(argv[i], "-baddns", 8) == 0) {
2607 			if (i + 1 < argc) {
2608 				bad_dns_dumpfile = argv[i + 1];
2609 				i++;
2610 			} else {
2611 				usage(stderr);
2612 				status = EXIT_FAILURE;
2613 				goto exit;
2614 			}
2615 		} else if (strncmp(argv[i], "-notip", 7) == 0) {
2616 			if (i + 1 < argc) {
2617 				not_ip_dumpfile = argv[i + 1];
2618 				i++;
2619 			} else {
2620 				usage(stderr);
2621 				status = EXIT_FAILURE;
2622 				goto exit;
2623 			}
2624 		} else if (strncmp(argv[i], "-c", 3) == 0) {
2625 			if (i + 1 < argc) {
2626 				if (!parse_match_list(count, argv[i + 1])) {
2627 					status = EXIT_FAILURE;
2628 					goto exit;
2629 				}
2630 				i++;
2631 			} else {
2632 				usage(stderr);
2633 				status = EXIT_FAILURE;
2634 				goto exit;
2635 			}
2636 		} else 	if (strncmp(argv[i], "-f", 3) == 0) {
2637 			if (i + 1 < argc) {
2638 				if (expr || strchr(argv[i+1], ',')) {
2639 					fprintf(stderr, "You can only specify 1 filter expression.\n");
2640 					status = EXIT_FAILURE;
2641 					goto exit;
2642 				}
2643 				expr = parse_match_expression(argv[i + 1]);
2644 				i++;
2645 			} else {
2646 				usage(stderr);
2647 				status = EXIT_FAILURE;
2648 				goto exit;
2649 			}
2650 		} else if (strncmp(argv[i], "-h", 3) == 0) {
2651 			usage(stdout);
2652 			status = EXIT_SUCCESS;
2653 			goto exit;
2654 		} else if (strncmp(argv[i], "-p", 3) == 0) {
2655 			show_percentages = true;
2656 		} else if (strncmp(argv[i], "-of", 4) == 0) {
2657 			if (i + 1 < argc) {
2658 				dumpfile = argv[i + 1];
2659 				i++;
2660 			} else {
2661 				usage(stderr);
2662 				status = EXIT_FAILURE;
2663 				goto exit;
2664 			}
2665 		} else if (strncmp(argv[i], "-ofh", 5) == 0) {
2666 			if (i + 1 < argc) {
2667 				hexdumpfilename = argv[i + 1];
2668 				i++;
2669 			} else {
2670 				usage(stderr);
2671 				status = EXIT_FAILURE;
2672 				goto exit;
2673 			}
2674 		} else if (strncmp(argv[i], "-s", 3) == 0) {
2675 			if (i + 1 < argc) {
2676 				show_match_names(argv[i + 1]);
2677 			} else {
2678 				show_match_names(NULL);
2679 			}
2680 			status = EXIT_SUCCESS;
2681 			goto exit;
2682 		} else if (strncmp(argv[i], "-sf", 4) == 0) {
2683 			show_filter_matches = true;
2684 		} else if (strncmp(argv[i], "-u", 3) == 0) {
2685 			if (i + 1 < argc) {
2686 				if (!parse_uniques(unique_ids, &unique_id_count, argv[i + 1])) {
2687 					status = EXIT_FAILURE;
2688 					goto exit;
2689 				}
2690 				i++;
2691 			} else {
2692 				usage(stderr);
2693 				status = EXIT_FAILURE;
2694 				goto exit;
2695 			}
2696 		} else if (strcmp("-ua", argv[i]) == 0) {
2697 			show_averages = true;
2698 		} else if (strcmp("-uac", argv[i]) == 0) {
2699 			show_average_count = true;
2700 		} else if (strcmp("-um", argv[i]) == 0) {
2701 			if (i + 1 < argc) {
2702 				unique_minimum = atoi(argv[i+1]);
2703 				i++;
2704 			} else {
2705 				fprintf(stderr, "-um requires an argument");
2706 				usage(stderr);
2707 				status = EXIT_FAILURE;
2708 				goto exit;
2709 			}
2710 		} else if (strcmp("-v", argv[i]) == 0) {
2711 			i++;
2712 			if (i < argc) {
2713 				verbosity = atoi(argv[i]);
2714 			}
2715 		} else if (strcmp("-version", argv[i]) == 0) {
2716 			printf("dns packet analyzer, version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
2717 			goto exit;
2718 		} else {
2719 			if (inputfile) {
2720 				fprintf(stderr, "You can only specify 1 input file\n");
2721 				exit(1);
2722 			}
2723 			inputfile = argv[i];
2724 		}
2725 	}
2726 
2727 	if (!inputfile) {
2728 		inputfile = "-";
2729 	}
2730 
2731 	if (verbosity >= 5) {
2732 		printf("Filter:\n");
2733 		print_match_expression(stdout, expr);
2734 		printf("\n\n");
2735 	}
2736 
2737 	pc = pcap_open_offline(inputfile, errbuf);
2738 
2739 	if (!pc) {
2740 		if (errno != 0) {
2741 			printf("Error opening pcap file %s: %s\n", inputfile, errbuf);
2742 			exit(1);
2743 		} else {
2744 			goto showresult;
2745 		}
2746 	}
2747 
2748 	if (dumpfile) {
2749 	        dumper = pcap_dump_open(pc, dumpfile);
2750 
2751 		if (!dumper) {
2752 			printf("Error opening pcap dump file %s: %s\n", dumpfile, errbuf);
2753 			exit(1);
2754 		}
2755 	}
2756 
2757 	if (hexdumpfilename) {
2758 		if (strncmp(hexdumpfilename, "-", 2) != 0) {
2759 			printf("hexdump is file\n");
2760 		        hexdumpfile = fopen(hexdumpfilename, "w");
2761 		} else {
2762 			printf("hexdump is stdout\n");
2763 			hexdumpfile = stdout;
2764 		}
2765 
2766 		if (!hexdumpfile) {
2767 			printf("Error opening hex dump file %s: %s\n", hexdumpfilename, strerror(errno));
2768 			exit(1);
2769 		}
2770 	}
2771 
2772 	if (not_ip_dumpfile) {
2773 		not_ip_dump = pcap_dump_open(pc, not_ip_dumpfile);
2774 		if (!not_ip_dump) {
2775 			printf("Error opening pcap dump file NOT_IP: %s\n",  errbuf);
2776 		}
2777 	}
2778 	if (bad_dns_dumpfile) {
2779 		bad_dns_dump = pcap_dump_open(pc, bad_dns_dumpfile);
2780 		if (!bad_dns_dump) {
2781 			printf("Error opening pcap dump file NOT_IP: %s\n",  errbuf);
2782 		}
2783 	}
2784 
2785 	while ((cur = pcap_next(pc, &cur_hdr))) {
2786 		if (verbosity >= 5) {
2787 			printf("\n\n\n[PKT_HDR] caplen: %u \tlen: %u\n", (unsigned int)cur_hdr.caplen, (unsigned int)cur_hdr.len);
2788 		}
2789 		handle_ether_packet(cur, cur_hdr, count, expr, uniques, unique_ids, unique_id_count);
2790 	}
2791 
2792 	if (not_ip_dump) {
2793 		pcap_dump_close(not_ip_dump);
2794 	}
2795 
2796 	if (bad_dns_dump) {
2797 		pcap_dump_close(bad_dns_dump);
2798 	}
2799 
2800 	if (dumper) {
2801 		pcap_dump_close(dumper);
2802 	}
2803 
2804 	if (hexdumpfile && hexdumpfile != stdout) {
2805 		fclose(hexdumpfile);
2806 	}
2807 
2808 	pcap_close(pc);
2809 
2810 	showresult:
2811 	if (show_percentages) {
2812 		fprintf(stdout, "Packets that are not IP: %u\n", (unsigned int) not_ip_packets);
2813 		fprintf(stdout, "bad dns packets: %u\n", (unsigned int) bad_dns_packets);
2814 		fprintf(stdout, "arp packets: %u\n", (unsigned int) arp_packets);
2815 		fprintf(stdout, "udp packets: %u\n", (unsigned int) udp_packets);
2816 		fprintf(stdout, "tcp packets (skipped): %u\n", (unsigned int) tcp_packets);
2817 		fprintf(stdout, "reassembled fragmented packets: %u\n", (unsigned int) fragmented_packets);
2818 		fprintf(stdout, "packet fragments lost: %u\n", (unsigned int) lost_packet_fragments);
2819 		fprintf(stdout, "Total number of DNS packets: %u\n", (unsigned int) total_nr_of_dns_packets);
2820 		fprintf(stdout, "Total number of DNS packets after filter: %u\n", (unsigned int) total_nr_of_filtered_packets);
2821 	}
2822 	if (count->match) {
2823 		print_counters(stdout, count, show_percentages, total_nr_of_filtered_packets, 0);
2824 	}
2825 	if (uniques->match) {
2826 		print_counters(stdout, uniques, show_percentages, total_nr_of_filtered_packets, unique_minimum);
2827 		if (show_averages) {
2828 			print_counter_averages(stdout, uniques, NULL);
2829 		}
2830 		if (show_average_count) {
2831 			print_counter_average_count(stdout, uniques, NULL, true);
2832 		}
2833 	}
2834 
2835 	exit:
2836 
2837 	free_match_expression(expr);
2838 	free_counters(count);
2839 	free_counters(uniques);
2840 
2841 	return status;
2842 }
2843 
2844 #else
main(void)2845 int main(void) {
2846 	fprintf(stderr, "ldns-dpa was not built because there is no pcap library on this system, or there was no pcap header file at compilation time. Please install pcap and rebuild.\n");
2847 	return 1;
2848 }
2849 #endif
2850 #else
main(void)2851 int main(void) {
2852 	fprintf(stderr, "ldns-dpa was not built because there is no pcap library on this system, or there was no pcap header file at compilation time. Please install pcap and rebuild.\n");
2853 	return 1;
2854 }
2855 #endif
2856 
2857 
2858