#!/usr/bin/perl -w # $Id: ip_inspect 1089 2018-12-19 10:45:41Z mueller $ # # Copyright 2017-2018 by Walter F.J. Mueller # # This program is free software; you may redistribute and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for complete details. # # Revision History: # Date Rev Version Comment # 2018-12-18 1089 0.1.1 add and use bailout # 2017-04-08 872 0.1 First draft # use 5.14.0; # require Perl 5.14 or higher use strict; # require strict checking use Getopt::Long; my %opts = (); GetOptions(\%opts, ) or bailout("bad command options"); autoflush STDOUT 1 if (-p STDOUT); # autoflush if output into pipe my $cmd = shift @ARGV; bailout("missing command; use 'ip_inspect help'") unless (defined $cmd); if ($cmd eq "help") { print_usage(); } elsif ($cmd eq "defeif") { do_defeif(); } elsif ($cmd eq "addr4") { do_addr4(); } elsif ($cmd eq "defroute") { do_defroute(); } else { bailout("invalid command '$cmd'"); } exit 0; #------------------------------------------------------------------------------- sub do_defeif { my @devs; open (IPRES, "ip link show|") or bailout("failed to call ip"); while () { chomp; next unless m|^\d+:\s*(\w+):|; my $dev = $1; next unless $dev =~ m/^(en|eth)/; push @devs,$dev; } close (IPRES); bailout("failed to detect default device") if (scalar(@devs) == 0); if (scalar(@devs) > 1) { my $devstr = join ',',@devs; bailout("multiple ethernet interfaces '$devstr'"); } print "$devs[0]\n"; return; } #------------------------------------------------------------------------------- sub do_addr4 { my $dev = shift @ARGV; my $fld = shift @ARGV; bailout("missing device or field") unless (defined $dev && defined $fld); my $addr; my $size; my $bcast; open (IPRES, "ip addr show dev $dev|") or bailout("failed to call ip"); while () { chomp; next unless m|^\s+inet\s+([0-9.]+)/(\d+)\s+brd\s+([0-9.]+)|; $addr = $1; $size = $2; $bcast = $3; } close (IPRES); if ($fld eq "addr") { print "$addr\n"; } elsif ($fld eq "addrm") { print "$addr/$size\n"; } elsif ($fld eq "mask") { my $mask = size2mask($size); print "$mask\n"; } elsif ($fld eq "bcast") { print "$bcast\n"; } else { bailout("invalid field '$fld'"); } return; } #------------------------------------------------------------------------------- sub do_defroute { open (IPRES, "ip route show|") or bailout("failed to call ip"); while () { chomp; if (m|^default via\s+([0-9.]+)|) { close (IPRES); print "$1\n"; return; } } bailout("failed to find default route"); } #------------------------------------------------------------------------------- sub size2mask { my ($size) = @_; my $bmask = ('1' x $size) . ('0' x (32-$size)); my $dmask = oct("0b".substr($bmask, 0,8)) . '.' . oct("0b".substr($bmask, 8,8)) . '.' . oct("0b".substr($bmask,16,8)) . '.' . oct("0b".substr($bmask,24,8)); return $dmask; } #------------------------------------------------------------------------------- sub bailout { my ($msg) = @_; print STDERR "ip_inspect-F: $msg\n"; exit 1; } #------------------------------------------------------------------------------- sub print_usage { print "usage: ip_inspect \n"; print " ip_inspect defeif # get default eth interface\n"; print " ip_inspect addr4 addrm # get ip4 addr/mask\n"; print " ip_inspect addr4 addr # get ip4 bare addr\n"; print " ip_inspect addr4 mask # get ip4 subnet mask\n"; print " ip_inspect addr4 bcast # get ip4 bcast addr\n"; print " ip_inspect defroute # get default route\n"; return; }