1#!/usr/bin/perl
2#
3# Copyright (C) 2004, 2007, 2012, 2013  Internet Systems Consortium, Inc. ("ISC")
4# Copyright (C) 2000, 2001  Internet Software Consortium.
5#
6# Permission to use, copy, modify, and/or distribute this software for any
7# purpose with or without fee is hereby granted, provided that the above
8# copyright notice and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16# PERFORMANCE OF THIS SOFTWARE.
17
18# Id: digcomp.pl,v 1.14 2007/06/19 23:47:00 tbox Exp
19
20# Compare two files, each with the output from dig, for differences.
21# Ignore "unimportant" differences, like ordering of NS lines, TTL's,
22# etc...
23
24$lc = 0;
25if ($ARGV[0] eq "--lc") {
26	$lc = 1;
27	shift;
28}
29$file1 = $ARGV[0];
30$file2 = $ARGV[1];
31
32$count = 0;
33$firstname = "";
34$status = 0;
35$rcode1 = "none";
36$rcode2 = "none";
37
38open(FILE1, $file1) || die("open: $file1: $!\n");
39while (<FILE1>) {
40	chomp;
41	if (/^;.+status:\s+(\S+).+$/) {
42		$rcode1 = $1;
43	}
44	next if (/^;/);
45	if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) {
46		$name = $1;
47		$class = $2;
48		$type = $3;
49		$value = $4;
50		if ($lc) {
51			$name = lc($name);
52			$value = lc($value);
53		}
54		if ($type eq "SOA") {
55			$firstname = $name if ($firstname eq "");
56			if ($name eq $firstname) {
57				$name = "$name$count";
58				$count++;
59			}
60		}
61		if ($entry{"$name ; $class.$type ; $value"} ne "") {
62			$line = $entry{"$name ; $class.$type ; $value"};
63			print("Duplicate entry in $file1:\n> $_\n< $line\n");
64		} else {
65			$entry{"$name ; $class.$type ; $value"} = $_;
66		}
67	}
68}
69close(FILE1);
70
71$printed = 0;
72
73open(FILE2, $file2) || die("open: $file2: $!\n");
74while (<FILE2>) {
75	chomp;
76	if (/^;.+status:\s+(\S+).+$/) {
77		$rcode2 = $1;
78	}
79	next if (/^;/);
80	if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) {
81		$name = $1;
82		$class = $2;
83		$type = $3;
84		$value = $4;
85		if ($lc) {
86			$name = lc($name);
87			$value = lc($value);
88		}
89		if (($name eq $firstname) && ($type eq "SOA")) {
90			$count--;
91			$name = "$name$count";
92		}
93		if ($entry{"$name ; $class.$type ; $value"} ne "") {
94			$entry{"$name ; $class.$type ; $value"} = "";
95		} else {
96			print("Only in $file2 (missing from $file1):\n")
97			    if ($printed == 0);
98			print("> $_\n");
99			$printed++;
100			$status = 1;
101		}
102	}
103}
104close(FILE2);
105
106$printed = 0;
107
108foreach $key (keys(%entry)) {
109	if ($entry{$key} ne "") {
110		print("Only in $file1 (missing from $file2):\n")
111		    if ($printed == 0);
112		print("< $entry{$key}\n");
113		$status = 1;
114		$printed++;
115	}
116}
117
118if ($rcode1 ne $rcode2) {
119	print("< status: $rcode1\n");
120	print("> status: $rcode2\n");
121	$status = 1;
122}
123
124exit($status);
125