source: MondoRescue/branches/3.0/mindi/mr-find-net@ 2967

Last change on this file since 2967 was 2967, checked in by Bruno Cornec, 12 years ago

r4568@cabanilles: bruno | 2012-03-15 14:14:57 +0100
mr-find-net now fully works

  • Property svn:executable set to *
File size: 5.1 KB
Line 
1#!/usr/bin/perl -w
2#
3# Syntax: mr-net-find <IP Addr>
4# finds on which network device the the server is
5# $Id$
6#
7# Copyright B. Cornec 2007-2012
8# Provided under the GPL v2
9
10# Syntax: see at end
11
12use strict 'vars';
13use Socket;
14use Data::Dumper;
15use Getopt::Long qw(:config auto_abbrev no_ignore_case);
16use English;
17#use lib qw (lib);
18use ProjectBuilder::Version;
19use ProjectBuilder::Base;
20
21=pod
22
23=head1 NAME
24
25mr-net-find, finds on which network device a machine is reachable
26
27=head1 DESCRIPTION
28
29mr-net-find, finds on which network device an machine is reachable
30It takes the IP or named looked at as single parameter and diagnose on which device it's reachable or gives NONET if it's not.
31
32=head1 SYNOPSIS
33
34mr-net-find [-v] NFS_SERVER_NAME
35
36=head1 OPTIONS
37
38=over 4
39
40=item B<-v|--verbose>
41
42Be more verbose
43
44=back
45
46=head1 WEB SITES
47
48The main Web site of the project is available at L<http://www.mondorescue.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.mondorescue.org/>.
49
50=head1 USER MAILING LIST
51
52
53=head1 AUTHORS
54
55The MondoRescue team L<http://www.mondorescue.org/> lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
56
57=head1 COPYRIGHT
58
59MondoRescue.org is distributed under the GPL v2.0 license
60described in the file C<COPYING> included with the distribution.
61
62=cut
63
64# Global variables
65my ($mrver,$mrrev) = pb_version_init();
66my $appname = "mr-net-find";
67my %opts; # CLI Options
68
69# Initialize the syntax string
70
71pb_syntax_init("$appname Version $mrver-$mrrev\n");
72
73GetOptions("help|?|h" => \$opts{'h'},
74 "man" => \$opts{'man'},
75 "verbose|v+" => \$opts{'v'},
76) || pb_syntax(-1,0);
77
78if (defined $opts{'h'}) {
79 pb_syntax(0,1);
80}
81if (defined $opts{'man'}) {
82 pb_syntax(0,2);
83}
84if (defined $opts{'v'}) {
85 $pbdebug = $opts{'v'};
86}
87pb_log_init($pbdebug, $pbLOG);
88
89
90# Check to which network an IP balongs
91sub mr_net_for_ip {
92
93my ($ip, $if) = @_;
94my $dev = undef;
95
96# For each device on the system
97foreach my $d (keys %$if) {
98 # Skip non fully activated interfaces
99 next if ((not defined $if->{$d}->{'nm'}) || (not defined $if->{$d}->{'net'}) || (not defined $if->{$d}->{'bcast'}));
100 # Get the net & bcast assuming the ip is on that net with that nm
101 my ($net,$bcast) = mr_net_nbcast_from_in ($ip,$if->{$d}->{'nm'});
102 # Is it true ?
103 if (($net eq $if->{$d}->{'net'}) && ($bcast eq $if->{$d}->{'bcast'})) {
104 # found it, return that value
105 $dev = $d;
106 last;
107 }
108}
109return($dev);
110}
111
112sub mr_net_find_all {
113
114my %if;
115my $if = \%if;
116
117my $curdev = "";
118open(IP,"ip addr |") || die "Unable to read IP config\n";
119while(<IP>) {
120 # Remove duplicate spaces
121 $_ =~ s/\s+/ /g;
122 pb_log(2,"Line: $_\n");
123 # Check for a new interface
124 my $tmp;
125 if (/^[0-9]+:/) {
126 my $dev;
127 my $rank;
128 ($rank,$dev,$tmp) = split(/:/);
129 pb_log(3,"$rank,$dev,$tmp");
130 $dev =~ s/\s*//;
131 $if->{$dev}->{'if'} = $dev;
132 $curdev = $dev;
133 }
134 ($tmp,$tmp,$if->{$curdev}->{'mac'},$tmp) = split(/ /) if (/^ link/);
135 ($tmp,$tmp,$if->{$curdev}->{'cidr'},$tmp) = split(/ /) if (/^ inet/);
136}
137close(IP);
138
139# Ideas Taken from http://nixcraft.com/shell-scripting/11398-simple-ipcalc-perl-script.html
140foreach my $dev (keys %if) {
141 next if (not defined $if->{$dev}->{'cidr'});
142 ($if->{$dev}->{'ip'},my $cidr) = split(/\//,$if->{$dev}->{'cidr'});
143
144 $if->{$dev}->{'nm'} = mr_net_cvt_bits_mask($cidr);
145
146 ($if->{$dev}->{'net'},$if->{$dev}->{'bcast'}) = mr_net_nbcast_from_in($if->{$dev}->{'ip'},$if->{$dev}->{'nm'});
147}
148pb_log(2,"exit IP: ".Dumper($if)."\n");
149
150return($if);
151}
152
153
154# Improved from http://icmp.ru/man/cisco/cookbook/ciscockbk-CHP-5-SECT-3.htm
155sub mr_net_cvt_bits_mask {
156
157my ($bits) = @_;
158my $a = 0;
159my $b = 0;
160my $c = 0;
161my $d = 0;
162
163if ($bits <= 8 ) {
164 $a = bits_to_dec($bits);
165} else {
166 $a = 255;
167 if ($bits <= 16 ) {
168 $b = bits_to_dec($bits-8);
169 } else {
170 $b=255;
171 if ($bits <= 24 ) {
172 $c = bits_to_dec($bits-16);
173 } else {
174 $c=255;
175 if ($bits <= 32 ) {
176 $d = bits_to_dec($bits-24);
177 } else {
178 die "invalid bit count\n";
179 }
180 }
181 }
182}
183return ($a.".".$b.".".$c.".".$d);
184}
185
186sub bits_to_dec {
187my ($bits) = @_;
188
189if ($bits == 0 ) { return 0; }
190if ($bits == 1 ) { return 128; }
191if ($bits == 2 ) { return 192; }
192if ($bits == 3 ) { return 224; }
193if ($bits == 4 ) { return 240; }
194if ($bits == 5 ) { return 248; }
195if ($bits == 6 ) { return 252; }
196if ($bits == 7 ) { return 254; }
197if ($bits == 8 ) { return 255; }
198}
199
200# Get Net and Broadcast from IP and Netmask
201sub mr_net_nbcast_from_in {
202
203my ($ip,$nm) = @_;
204my ($ipaddress) = unpack("N",pack( "C4",split(/\./,$ip)));
205my ($netmask) = unpack( "N", pack( "C4",split(/\./,$nm)));
206
207# Calculate network address by logical AND operation of addr & netmask
208# and convert network address to IP address format
209my $net = join(".",unpack("C4",pack("N",($ipaddress & $netmask))));
210
211# Calculate broadcase address by inverting the netmask
212# and do a logical or with network address
213my $bcast = join(".",unpack("C4",pack("N",($ipaddress & $netmask)+(~ $netmask))));
214return($net,$bcast);
215}
216
217#Main
218
219my $nfsip = inet_ntoa(scalar gethostbyname($ARGV[0] || 'localhost'));
220
221my $if = mr_net_find_all();
222pb_log(1,"IP: ".Dumper($if)."\n");
223my $dev = mr_net_for_ip($nfsip,$if);
224my $strnet = "NONET";
225$strnet = $dev if (defined $dev);
226pb_log(1,"NFS IP ($nfsip) is on net $strnet)\n");
227pb_log(0,"$strnet\n");
Note: See TracBrowser for help on using the repository browser.