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

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

r4571@cabanilles: bruno | 2012-03-15 16:26:08 +0100

  • Working mr-net-find for both ip and ifconfig
  • Property svn:executable set to *
File size: 7.3 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 = "";
118# TODO: Check whther the ip command is available !
119# If not consider using ifconfig for compatibility or non Linux availability
120my $ipcmd = pb_check_req("ip",1);
121if (defined $ipcmd) {
122 open(IP,"$ipcmd addr |") || die "Unable to read IP config with $ipcmd addr\n";
123 while (<IP>) {
124 # Remove duplicate spaces
125 my $line = $_;
126 $line =~ s/\s+/ /g;
127 pb_log(2,"Line: $line\n");
128 # Check for a new interface
129 my $tmp;
130 if ($line =~ /^[0-9]+:/) {
131 my $dev;
132 my $rank;
133 ($rank,$dev,$tmp) = split(/:/,$line);
134 pb_log(3,"$rank,$dev,$tmp\n");
135 $dev =~ s/\s*//;
136 $if->{$dev}->{'if'} = $dev;
137 $curdev = $dev;
138 }
139 ($tmp,$tmp,$if->{$curdev}->{'mac'},$tmp) = split(/ /,$line) if (/^\s*link/);
140 ($tmp,$tmp,$if->{$curdev}->{'cidr'},$tmp) = split(/ /,$line) if (/^\s*inet/);
141 }
142 close(IP);
143} else {
144 my $ipcmd = pb_check_req("ifconfig",1);
145 if (defined $ipcmd) {
146 open(IP,"$ipcmd -a |") || die "Unable to read IP config with $ipcmd -a\n";
147 while (<IP>) {
148 # Remove duplicate spaces
149 my $line = $_;
150 $line =~ s/\s+/ /g;
151 pb_log(2,"Line: $line\n");
152 # Check for a new interface
153 my $tmp;
154 my $tmp2;
155 if ($line =~ /^[^ ]+ /) {
156 my $dev;
157 ($dev,$tmp) = split(/ /,$line,2);
158 pb_log(3,"DEV: $dev,$tmp\n");
159 $dev =~ s/\s*//;
160 $if->{$dev}->{'if'} = $dev;
161 $curdev = $dev;
162 ($tmp2,$tmp2,$tmp2,$if->{$curdev}->{'mac'}) = split(/ /,$tmp);
163 }
164 if (/^\s*inet/) {
165 ($tmp,$if->{$curdev}->{'ip'},$if->{$curdev}->{'nm'},$tmp) = split(/:/,$line);
166 $if->{$curdev}->{'ip'} =~ s/ .*$// if (defined $if->{$curdev}->{'ip'});
167 $if->{$curdev}->{'nm'} =~ s/ .*$// if (defined $if->{$curdev}->{'nm'});
168 pb_log(3,"IP: $if->{$curdev}->{'ip'},$if->{$curdev}->{'nm'}\n");
169 $if->{$curdev}->{'cidr'} = $if->{$curdev}->{'ip'}."/".mr_net_cvt_mask_bits($if->{$curdev}->{'nm'}) if ((defined $if->{$curdev}->{'ip'}) && (defined $if->{$curdev}->{'nm'}));
170 }
171 }
172 close(IP);
173 } else {
174 die "Neither ip nor ifconfig are available to get IP configuration.\nPlease report upstream how to deal with your platform.\n";
175 }
176}
177
178# Ideas Taken from http://nixcraft.com/shell-scripting/11398-simple-ipcalc-perl-script.html
179foreach my $dev (keys %if) {
180 next if (not defined $if->{$dev}->{'cidr'});
181 ($if->{$dev}->{'ip'},my $cidr) = split(/\//,$if->{$dev}->{'cidr'}) if (not defined $if->{$dev}->{'ip'});
182
183 $if->{$dev}->{'nm'} = mr_net_cvt_bits_mask($cidr) if (not defined $if->{$dev}->{'nm'});;
184
185 ($if->{$dev}->{'net'},$if->{$dev}->{'bcast'}) = mr_net_nbcast_from_in($if->{$dev}->{'ip'},$if->{$dev}->{'nm'});
186}
187pb_log(2,"exit IP: ".Dumper($if)."\n");
188
189return($if);
190}
191
192
193# Improved from http://icmp.ru/man/cisco/cookbook/ciscockbk-CHP-5-SECT-3.htm
194sub mr_net_cvt_bits_mask {
195
196my ($bits) = @_;
197my $a = 0;
198my $b = 0;
199my $c = 0;
200my $d = 0;
201
202if ($bits <= 8 ) {
203 $a = mr_net_bits_to_dec($bits);
204} else {
205 $a = 255;
206 if ($bits <= 16 ) {
207 $b = mr_net_bits_to_dec($bits-8);
208 } else {
209 $b=255;
210 if ($bits <= 24 ) {
211 $c = mr_net_bits_to_dec($bits-16);
212 } else {
213 $c=255;
214 if ($bits <= 32 ) {
215 $d = mr_net_bits_to_dec($bits-24);
216 } else {
217 die "invalid bit count\n";
218 }
219 }
220 }
221}
222return ($a.".".$b.".".$c.".".$d);
223}
224
225sub mr_net_cvt_mask_bits {
226
227my ($mask) = @_;
228my ($a,$b,$c,$d) = split(/\./,$mask);
229my $bits =0;
230
231$bits= mr_net_dec_to_bits($a) + mr_net_dec_to_bits($b) + mr_net_dec_to_bits($c) + mr_net_dec_to_bits($d);
232return ($bits);
233}
234
235sub mr_net_bits_to_dec {
236my ($bits) = @_;
237
238if ($bits == 0 ) { return 0; }
239if ($bits == 1 ) { return 128; }
240if ($bits == 2 ) { return 192; }
241if ($bits == 3 ) { return 224; }
242if ($bits == 4 ) { return 240; }
243if ($bits == 5 ) { return 248; }
244if ($bits == 6 ) { return 252; }
245if ($bits == 7 ) { return 254; }
246if ($bits == 8 ) { return 255; }
247}
248
249sub mr_net_dec_to_bits {
250my ($dec) = @_;
251
252if ($dec == 0 ) { return 0; }
253if ($dec == 128 ) { return 1; }
254if ($dec == 192 ) { return 2; }
255if ($dec == 224 ) { return 3; }
256if ($dec == 240 ) { return 4; }
257if ($dec == 248 ) { return 5; }
258if ($dec == 252 ) { return 6; }
259if ($dec == 254 ) { return 7; }
260if ($dec == 255 ) { return 8; }
261}
262
263# Get Net and Broadcast from IP and Netmask
264sub mr_net_nbcast_from_in {
265
266my ($ip,$nm) = @_;
267my ($ipaddress) = unpack("N",pack( "C4",split(/\./,$ip)));
268my ($netmask) = unpack( "N", pack( "C4",split(/\./,$nm)));
269
270# Calculate network address by logical AND operation of addr & netmask
271# and convert network address to IP address format
272my $net = join(".",unpack("C4",pack("N",($ipaddress & $netmask))));
273
274# Calculate broadcase address by inverting the netmask
275# and do a logical or with network address
276my $bcast = join(".",unpack("C4",pack("N",($ipaddress & $netmask)+(~ $netmask))));
277return($net,$bcast);
278}
279
280#Main
281
282my $nfsip = inet_ntoa(scalar gethostbyname($ARGV[0] || 'localhost'));
283
284my $if = mr_net_find_all();
285pb_log(1,"IP: ".Dumper($if)."\n");
286my $dev = mr_net_for_ip($nfsip,$if);
287my $strnet = "NONET";
288$strnet = $dev if (defined $dev);
289pb_log(1,"NFS IP ($nfsip) is on net $strnet)\n");
290pb_log(0,"$strnet\n");
Note: See TracBrowser for help on using the repository browser.