Zizzencs
Zizzencs

Reputation: 5128

How can I determine the local machine's IP addresses from Perl?

Is there a clean and OS independent way to determine the local machine's IP addresses from Perl?

So far I have found the following solutions:

Any better suggestion?

Upvotes: 16

Views: 48375

Answers (11)

VonC
VonC

Reputation: 1323115

You also have some other options, including your solution to "establish a network connection to a well-known IP and examine the socket's local IP address".

In that case (establishing network connection) however, that article points out that:

there is no such thing as a host's IP address.
Network interfaces have IP addresses, not hosts, and a single network interface can have many (virtual) IP addresses. The operating system's routing subsystem decides which network interface and IP address to use to connect to a remote machine.

If your machine only has one external network interface, and this interface only has one IP address then this IP address is commonly called the machine's address, but that is inaccurate.
For example, if the machine is connected to a VPN via a virtual interface it will use this interface's IP address to connect to another machine on the VPN, not the external IP address

Amongst the other solutions: Sys::Hostname - works if it comes up with a resolvable hostname.

use Sys::Hostname;
use Socket;
my $addr = inet_ntoa((gethostbyname(hostname))[4]);
print "$addr\n";

Upvotes: 18

PodTech.io
PodTech.io

Reputation: 5254

I have used a combination of these Linux commands so no dependancy on any perl module.

hostname -i
hostname -I
ls /sys/class/net
ip -f inet addr show eth0| grep -Po 'inet \K[\d.]+'

Upvotes: -1

Matt
Matt

Reputation: 1069

for windows I use

foreach (split(/\r?\n/,`netstat -r`))
{
  next unless /^\s+0.0.0.0/;
  @S = split(/\s+/); 
  # $S[3] = Default Gateway
  # $S[4] = Main IP
}

The first line starting 0.0.0.0 is the default gateway. There maybe multiple gateways. Lines starting 255.255.255.255 are also useful. netstat -r and route print are the same.

Can be adapted for OSX, Linux not so helpful.

Upvotes: 0

evgeny9
evgeny9

Reputation: 1441

Perldoc has an answer to this question in its FAQ ("perlfaq9") - using different modules (which are parts of the Standard Library) or even a built-in function.

Upvotes: 4

dolmen
dolmen

Reputation: 8696

To retrieve the IP address of all interfaces, use IO::Interface::Simple:

perl -MIO::Interface::Simple '-Esay $_->address for grep { $_->is_running && defined $_->address } IO::Interface::Simple->interfaces'

If you are not interested in 127.0.0.1 (loopback) you can filter on $_->is_loopback.

Upvotes: 7

Tommy Stanton
Tommy Stanton

Reputation: 756

In my case, I need a solution without any non-core dependencies. I came up with this after studying the code in Net::Address::IP::Local:

#!/usr/bin/env perl

use strict;
use warnings;

use IO::Socket::INET;

my $local_ip_address = get_local_ip_address();

print "$local_ip_address\n";

# This idea was stolen from Net::Address::IP::Local::connected_to()
sub get_local_ip_address {
    my $socket = IO::Socket::INET->new(
        Proto       => 'udp',
        PeerAddr    => '198.41.0.4', # a.root-servers.net
        PeerPort    => '53', # DNS
    );

    # A side-effect of making a socket connection is that our IP address
    # is available from the 'sockhost' method
    my $local_ip_address = $socket->sockhost;

    return $local_ip_address;
}

get_local_ip_address() should return the same string as Net::Address::IP::Local->public_ipv4.

If desired, you can change the PeerAddr attribute (in the arguments to the constructor for IO::Socket::INET) to a local DNS server.

Upvotes: 16

golimar
golimar

Reputation: 2548

Net::Address::IP::Local works fine, but since the original poster asks for all the local addresses, I think this one is better:

http://www.perlmonks.org/?node_id=166951

It worked fine for me with ActivePerl for Windows XP.

Upvotes: 0

Leon Timmermans
Leon Timmermans

Reputation: 30225

Net::Address::IP::Local looks promising.

use Net::Address::IP::Local;

# Get the local system's IP address that is "en route" to "the internet":
my $address      = Net::Address::IP::Local->public;

Upvotes: 18

converter42
converter42

Reputation: 7516

I've had good success with IO::Interface on Linux and Solaris, and I think it even worked on AIX but I can't recall for sure. Poking around on search.cpan.org, rt.cpan.org and ActiveState's various sites, it looks like IO::Interface may be experiencing build problems on Windows. I guess the only way to know if it's available is to search for io-interface in PPM.

Upvotes: 1

The Archetypal Paul
The Archetypal Paul

Reputation: 41749

use WMI?

Example of extracting IP addresses (in Powershell, but it's pretty clear what's happening)

Example of accessing WMI from Perl (not the same WMI functions, but again the process is reasonably clear)

EDIT: after a search on Google codesearch for Networkadapterconfiguration and language "perl":

Example looks like pretty much what you need

EDIT2: In fact the OCS code seems to contain code for most platforms to do this, so while there may be no one set of code that does this, you may be able to re-use their ideas. It's GPL'd, though.

For example, here's the Solaris code. Other bits cover BSD, Linux, MacOS...

Upvotes: 0

Related Questions