source: branches/3.0/mindi/mr-net-find @ 3153

Last change on this file since 3153 was 2969, checked in by bruno, 7 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.