Sys-HostAddr
view release on metacpan or search on metacpan
HostAddr.pm view on Meta::CPAN
}elsif($self->{ipv} eq '6' && $line =~ m#(/\d{1,3})$#){
$netmask = $1;
}else{
die "unknown netmask for $addr on $interface\n";
}
push @{$data{$interface}}, { address => $addr, netmask => $netmask };
}elsif($line =~ /^\s+Description[\s\.]+:\s([^\r\n]+)/){
$interface = $1;
}elsif($line =~ /^\s+${ipv}[\s\.]+:\s+([a-f0-9:\.]{3,40})/){
$addr = $1; # win7
}elsif($line =~ /^\s+IP Address[\s\.]+:\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/){
$addr = $1 if($self->{ipv} eq '4'); # winXP IPv4
}elsif($line =~ /^\s+IP Address[\s\.]+:\s+([a-f0-9:\.]{3,40})/){
$addr = $1 if($self->{ipv} eq '6'); # winXP IPv6
}elsif($line =~ /^\s+Subnet Mask[\s\.]+:\s+(\S+)/){
$netmask = $1;
#this handles multiple ip addrs on same interface (tested on XP, anyway)
push @{$data{$interface}}, { address => $addr, netmask => $netmask };
}
}
return \%data;
}
sub first_ip {
my $self = shift;
my $getint = shift || $self->{interface};
my $cfg_aref = $self->ifconfig( $getint );
for (@{$cfg_aref}){
my $addr;
if(/^\s+${ipv}\s+(?:addr:)?(\S+)\s/){
$addr = $1; # unix
}elsif(/^\s+${ipv}[\s\.]+:\s+([a-f0-9:\.]{3,40})/){
$addr = $1; # windows 7 win32
}elsif(/^\s+IP Address[\s\.]+:\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/){
$addr = $1 if($self->{ipv} eq '4'); # winxp ipv4
}elsif(/^\s+IP Address[\s\.]+:\s+([a-f0-9:\.]{3,40})/){
$addr = $1 if($self->{ipv} eq '6'); # winxp ipv6
}
if($addr){
next if($addr =~ /^(?:127\.|::1)/); # never say ln is first
return( $addr );
}
}
die "couldnt find first $ipv IP Address\n";
}
sub ifconfig {
my $self = shift;
my $getint = shift || $self->{interface};
my ($cmd,$param);
if($^O eq 'MSWin32' || $^O eq 'cygwin'){
$cmd = 'ipconfig';
$param = '/all';
}else{
$cmd = 'ifconfig';
$param = $getint || '-a';
$param .= ' inet6' if($self->{ipv} eq '6' && $^O eq 'solaris');
}
my @config = $self->_get_stdout($cmd, $param);
return( \@config );
}
sub main_ip {
my $self = shift;
my $method = shift || 'auto';
if( $method eq 'preferred' && ($^O ne 'MSWin32' && $^O ne 'cygwin') ){
die "'preferred' method to main_ip available on MSWin32/cygwin only.\n";
}
unless($method =~ /^(?:dns|route|preferred|auto)$/){
die "invalid method given to main_ip\n";
}
if($method eq 'dns' || $method eq 'auto'){
my $addr;
my $hostname = hostname();
$self->_debug( "attempting hostname lookup in main_ip: $hostname" );
eval {
local $SIG{ALRM} = sub { die "timeout on $hostname\n" };
alarm(3);
my @x = ( gethostbyname($hostname) )[4];
alarm(0);
verbose( "multiple ip addrs found for $hostname" ) if(@x > 1);
$addr = join( '.', unpack('C4', $x[0]) );
};
alarm(0);
if($@){
$self->_warn($@);
}
if( $addr ){
return $addr unless($addr =~ /^(?:127\.|::1)/); # never say lo is main
}
$self->_debug( "DNS lookup did not yield an IP addr." );
}
if($method eq 'route' || $method eq 'auto'){
# if dns method failed us, check for default route, find local ip
# addr(s) in same subnet -"first" one listed will be called "main"
my ($cmd,$param);
if($^O eq 'solaris'){
$cmd = 'route';
$param = 'get 0.0.0.0';
}else{
$cmd = 'netstat'; # works with MSWin32, too
$param = '-nr';
}
my @data = $self->_get_stdout($cmd, $param);
for my $line (@data){
chomp $line;
if($line =~ /^\s+0\.0\.0\.0\s+0\.0\.0\.0\s+\S+\s+(\S+)\s+/){
return( $1 ); # mswin32
}elsif($line =~ /^(?:0\.0\.0\.0|default)\s.*\s(\S+)$/){
# 0.0.0.0 = debian linux, default = freebsd
return( $self->first_ip($1) );
}elsif($line =~ /^\s+interface:\s+(\S+)$/){
return( $self->first_ip($1) ); # solaris
}
}
}
if($^O eq 'MSWin32' || $^O eq 'cygwin'){
if($method eq 'preferred' || $method eq 'auto'){
my $cfg_aref = $self->ifconfig();
foreach (@{$cfg_aref}){
if(/^\s+${ipv}[\s\.]+:\s+(\S+)\(Preferred\)/){
return($1);
}
}
}
}
die "could not determine main ip address\n"; # we dont pick one at random
}
sub _mkipv {
my $self = shift;
return ( ($^O eq 'MSWin32' || $^O eq 'cygwin') && $self->{ipv} eq '6' ) ? 'IPv6 Address' :
($^O eq 'MSWin32' || $^O eq 'cygwin') ? 'IPv4 Address' :
($self->{ipv} eq '6') ? 'inet6' :
'inet';
}
sub _get_stdout {
my $self = shift;
my $cmd = shift || die "get_stdout syntax error1\n";
my $params = join(' ', @_);
$self->_debug( "running cmd: [$cmd] params: [$params]" );
open(my $fh, "$cmd $params |") || die "cannot fork $cmd: $!\n"; # -| is 5.8+
my @data = <$fh>;
close $fh;
return( @data );
}
sub _warn {
my $self = shift;
my $msg = join('', @_);
warn "$self->{class}: $msg\n";
}
sub _debug {
my $self = shift;
$self->_warn(@_) if($self->{debug});
}
1;
__END__
=pod
=head1 NAME
Sys::HostAddr - Get IP address information about this host
=head1 SYNOPSIS
use Sys::HostAddr;
my $sysaddr = Sys::HostAddr->new();
my $string = $sysaddr->public();
my $aref = $sysaddr->interfaces();
my $aref = $sysaddr->addresses();
my $href = $sysaddr->ip();
my $ip = $sysaddr->first_ip();
my $main = $sysaddr->main_ip();
( run in 1.086 second using v1.01-cache-2.11-cpan-39bf76dae61 )