rev |
line source |
igor@0
|
1 #!/usr/bin/perl -w
|
igor@0
|
2 #
|
igor@0
|
3 use Net::IP qw(:PROC);
|
igor@0
|
4
|
igor@0
|
5 our $traceroute_options="-q1 -n -I";
|
igor@0
|
6 our $hops_to_highlight=4;
|
igor@0
|
7 our $verbose =1;
|
igor@0
|
8 our $prefixes="prefixes.txt";
|
igor@0
|
9 our $scale=1;
|
igor@0
|
10
|
igor@0
|
11 our $dot_file="tracemap.dot";
|
igor@0
|
12 our $svg_file="tracemap.svg";
|
igor@0
|
13 our $png_file="tracemap.png";
|
igor@0
|
14
|
igor@0
|
15 #our @printed_hops;
|
igor@0
|
16 our $graph="";
|
igor@0
|
17 our $hop_id = 0;
|
igor@0
|
18 our %hop_id;
|
igor@0
|
19
|
igor@0
|
20 our $previous_hop;
|
igor@0
|
21 our $previous_time;
|
igor@0
|
22 our $hop;
|
igor@0
|
23 our $time;
|
igor@0
|
24 our $ttl;
|
igor@0
|
25
|
igor@0
|
26 our %color_table=qw(
|
igor@0
|
27 194.150.0.0/16 red
|
igor@0
|
28 10.0.0.0/16 seagreen2
|
igor@0
|
29 10.1.0.0/16 seashell2
|
igor@0
|
30 10.2.0.0/16 sienna2
|
igor@0
|
31 10.3.0.0/16 skyblue2
|
igor@0
|
32 10.4.0.0/16 slateblue2
|
igor@0
|
33 10.5.0.0/16 slategray2
|
igor@0
|
34 10.6.0.0/16 snow1
|
igor@0
|
35 10.7.0.0/16 springgreen1
|
igor@0
|
36 10.8.0.0/16 steelblue1
|
igor@0
|
37 );
|
igor@0
|
38
|
igor@0
|
39 our @prefixes;
|
igor@0
|
40
|
igor@0
|
41 sub load_prefixes
|
igor@0
|
42 {
|
igor@0
|
43 my @prefixes=();
|
igor@0
|
44 open(PREFIXES, $prefixes);
|
igor@0
|
45 while (<PREFIXES>) { chomp; push @prefixes, $_;};
|
igor@0
|
46 close(PREFIXES);
|
igor@0
|
47 return @prefixes;
|
igor@0
|
48 }
|
igor@0
|
49
|
igor@0
|
50 sub ip_in_range
|
igor@0
|
51 {
|
igor@0
|
52 my $ip=shift;
|
igor@0
|
53 my $range_found=0;
|
igor@0
|
54 for my $range (@_) {
|
igor@0
|
55 my ($range_ip, $range_prefix) = split m@/@, $range;
|
igor@0
|
56 my ($ip1, $ip2) = ip_prefix_to_range($range_ip, $range_prefix,4);
|
igor@0
|
57 # print "$range\n";
|
igor@0
|
58 $range_found=ip_bincomp(ip_iptobin($ip1,4),'lt',ip_iptobin($ip,4))
|
igor@0
|
59 && ip_bincomp(ip_iptobin($ip,4),'lt',ip_iptobin($ip2,4));
|
igor@0
|
60 if ($range_found) {
|
igor@0
|
61 return $range;
|
igor@0
|
62 }
|
igor@0
|
63 }
|
igor@0
|
64 return 0;
|
igor@0
|
65 }
|
igor@0
|
66
|
igor@0
|
67 sub color_of_ip($)
|
igor@0
|
68 {
|
igor@0
|
69 my $ip = shift;
|
igor@0
|
70 for $range (keys %color_table) {
|
igor@0
|
71 if (ip_in_range($ip,$range)) {
|
igor@0
|
72 return $color_table{"$range"};
|
igor@0
|
73 }
|
igor@0
|
74 }
|
igor@0
|
75 return "indigo";
|
igor@0
|
76 }
|
igor@0
|
77
|
igor@0
|
78 sub print_hop($)
|
igor@0
|
79 {
|
igor@0
|
80 $hop = shift;
|
igor@0
|
81 unless (defined($hop_id{$hop})) {
|
igor@0
|
82 $hop_id++;
|
igor@0
|
83 $color="";
|
igor@0
|
84 $shape="";
|
igor@0
|
85 if (ip_in_range($hop, @prefixes)) {
|
igor@0
|
86 $color=",color=green"
|
igor@0
|
87 }
|
igor@0
|
88 $color=",color=".color_of_ip($hop);
|
igor@0
|
89 if ($ttl == $hops_to_highlight+1) {
|
igor@0
|
90 $shape=",shaper=rectangle"
|
igor@0
|
91 }
|
igor@0
|
92 $graph .= "hop$hop_id [ label=\"$hop\"$color$shape];";
|
igor@0
|
93 $hop_id{$hop} = $hop_id;
|
igor@0
|
94 }
|
igor@0
|
95 }
|
igor@0
|
96
|
igor@0
|
97 sub time_to_len($$)
|
igor@0
|
98 {
|
igor@0
|
99 $a=shift;
|
igor@0
|
100 $b=shift;
|
igor@0
|
101 $l=$a-$b;
|
igor@0
|
102 $l = 0.25 if $l<0.25;
|
igor@0
|
103 return (3+1.2*log($l))*0.3285*$scale;
|
igor@0
|
104 }
|
igor@0
|
105 sub say
|
igor@0
|
106 {
|
igor@0
|
107 print @_ if $verbose;
|
igor@0
|
108 }
|
igor@0
|
109
|
igor@0
|
110 sub ping_sweep($)
|
igor@0
|
111 {
|
igor@0
|
112 my $net = shift;
|
igor@0
|
113 my @res;
|
igor@0
|
114 say("Doing ping sweep of the $net IP-addresses block");
|
igor@0
|
115 open(NMAP, "nmap -sP $net|grep 'appears to be up' | awk '{print \$2}'|")
|
igor@0
|
116 or die "can't make ping sweep of $net. Have you nmap installed?\n$!";
|
igor@0
|
117 while (<NMAP>) {
|
igor@0
|
118 chomp;
|
igor@0
|
119 push (@res, ($_));
|
igor@0
|
120 say(".");
|
igor@0
|
121 }
|
igor@0
|
122 say("Done. $#res host(s) found.\n");
|
igor@0
|
123 return @res;
|
igor@0
|
124 }
|
igor@0
|
125
|
igor@0
|
126 sub dns_axfr($)
|
igor@0
|
127 {
|
igor@0
|
128 my @res;
|
igor@0
|
129 my ($zone,$ns) = split /@/;
|
igor@0
|
130 if ($ns eq '') {
|
igor@0
|
131 }
|
igor@0
|
132 else
|
igor@0
|
133 {
|
igor@0
|
134 say("Doing axfr of the zone $zone from the server $ns\n");
|
igor@0
|
135 open(DIG, "dig \@$ns axfr $zone | awk '/\tA\t/ {print \$1}' |")
|
igor@0
|
136 or die "can't make axfr of the zone $zone from the server $ns. Have you dig installed?\n$!";
|
igor@0
|
137 while (<DIG>) {
|
igor@0
|
138 chomp;
|
igor@0
|
139 push (@res, ($_));
|
igor@0
|
140 }
|
igor@0
|
141 say("Done. $#res host(s) found.\n");
|
igor@0
|
142 return @res;
|
igor@0
|
143 }
|
igor@0
|
144 }
|
igor@0
|
145
|
igor@0
|
146 my @dests=();
|
igor@0
|
147 while(<>)
|
igor@0
|
148 {
|
igor@0
|
149 chomp;
|
igor@0
|
150 next if /^#/;
|
igor@0
|
151 if (m@http:@) {
|
igor@0
|
152 }
|
igor@0
|
153 elsif (m@/@) {
|
igor@0
|
154 push(@dests,ping_sweep($_))
|
igor@0
|
155 }
|
igor@0
|
156 elsif (m'@') {
|
igor@0
|
157 push (@dests,dns_axfr($_))
|
igor@0
|
158 }
|
igor@0
|
159 else {
|
igor@0
|
160 push(@dests,($_));
|
igor@0
|
161 }
|
igor@0
|
162 }
|
igor@0
|
163
|
igor@0
|
164 @prefixes=load_prefixes();
|
igor@0
|
165
|
igor@0
|
166 for $dest (@dests)
|
igor@0
|
167 {
|
igor@0
|
168 say("Tracing path to $dest");
|
igor@0
|
169 open (TRACE,"traceroute $traceroute_options $dest|")
|
igor@0
|
170 or die "Can't run traceroute:$!";
|
igor@0
|
171 my $hop='';
|
igor@0
|
172 $ttl=0;
|
igor@0
|
173 my $total=0;
|
igor@0
|
174 while (<TRACE>) {
|
igor@0
|
175 chomp;
|
igor@0
|
176 next if not /ms/;
|
igor@0
|
177 say(".");
|
igor@0
|
178 $ttl++;
|
igor@0
|
179 s@^\s*@@;
|
igor@0
|
180 $previous_hop=$hop;
|
igor@0
|
181 $previous_time=$time;
|
igor@0
|
182 my $a;
|
igor@0
|
183 ($a, $hop, $time) = split(/\s+/, $_, 3);
|
igor@0
|
184 $time =~ s/\s*ms\s*$//;
|
igor@0
|
185 $total += $time;
|
igor@0
|
186 if ($previous_hop eq '') {
|
igor@0
|
187 print_hop($hop);
|
igor@0
|
188 $graph =~ s@color=[^],]*[],]@@;
|
igor@0
|
189 $graph =~ s@(\ label=\")[^"]*(\".*?)$@fontsize=10,color=red,style=filled,label="(YOU)$2@;
|
igor@0
|
190 }
|
igor@0
|
191 elsif (not defined $hop_id{$hop} ) {
|
igor@0
|
192 print_hop($previous_hop);
|
igor@0
|
193 print_hop($hop);
|
igor@0
|
194 $graph .= "hop".$hop_id{$previous_hop}." -- hop".$hop_id{$hop}.
|
igor@0
|
195 " [label=\"".sprintf("%1.2f",+$time-$previous_time)."\",len=".time_to_len($time,$previous_time)."];\n";
|
igor@0
|
196 }
|
igor@0
|
197 }
|
igor@0
|
198 $graph =~ s@(\ label=\")[^"]*(\".*?)$@fontsize=8,style=filled,label=\"$dest$2@;
|
igor@0
|
199 close(TRACE);
|
igor@0
|
200 say("Done [last $time, total $total]\n");
|
igor@0
|
201 }
|
igor@0
|
202 #$temp=rand.rand;
|
igor@0
|
203
|
igor@0
|
204 open (DOT, ">$dot_file")
|
igor@0
|
205 or die "can;t open dot file file for writing: $!";
|
igor@0
|
206 print DOT <<EOF;
|
igor@0
|
207 graph G {
|
igor@0
|
208 margin =1 ;
|
igor@0
|
209 node [fontname=times,fontsize=7,shape=circle,width=0.1,height=0.1,fixedsize=true,color=blue];
|
igor@0
|
210 edge [fontname=times,fontsize=5,color=black];
|
igor@0
|
211 $graph
|
igor@0
|
212 }
|
igor@0
|
213 EOF
|
igor@0
|
214 close(DOT);
|
igor@0
|
215
|
igor@0
|
216 print `neato -o $png_file -Tpng $dot_file > /dev/null 2>&1; neato -o $svg_file -Tsvg $dot_file > /dev/null 2>&1 `
|
igor@0
|
217 or die "can't run neato: $!;\ngraphviz is installed?\nYou can tracemap.dot to the hosts where graphviz in installed and run\nneato -o tracemap.png -Tpng tracemap.dot"
|
igor@0
|
218
|