Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

How do I get the local internet IP address?

by Anonymous Monk
on Jan 23, 2001 at 07:26 UTC ( [id://53660]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question: (network programming)

How do I get the local internet IP address?

Originally posted as a Categorized Question.

  • Comment on How do I get the local internet IP address?

Replies are listed 'Best First'.
Re: How do I get the local internet IP address?
by tirwhan (Abbot) on Jan 07, 2006 at 19:38 UTC

    This question is usually asked to find out which IP address the local host uses to connect to a remote one. One important thing to realise in this context is 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.

    Usually the best fail-safe way to find the "local Internet IP address" is to actually establish a network connection to the remote host and then find out which IP address is being used on the local side. For example:

    use IO::Socket::INET; my $sock = IO::Socket::INET->new( PeerAddr=> "example.com", PeerPort=> 80, Proto => "tcp"); my $localip = $sock->sockhost;
Re: How do I get the local internet IP address?
by kschwab (Vicar) on Jan 23, 2001 at 19:28 UTC
    Works if Sys::Hostname comes up with a resolvable hostname.
    use Sys::Hostname qw(hostname); # not strictly necessary; exports it b +y default use Socket; my($addr) = inet_ntoa( (gethostbyname(hostname()))[4] ); print "$addr\n";
Re: How do I get the local internet IP address?
by tye (Sage) on Jan 23, 2001 at 11:49 UTC
Re: How do I get the local internet IP address?
by arhuman (Vicar) on Jan 23, 2001 at 14:04 UTC
    Non portable, return the ip address of all hosts found in /etc/hosts...

    while (@adrs=(gethostent())[4]) { for my $value (@adrs) { print join '.',unpack('C4',$value); print "\n"; } }


      Or the more perlish (read : normal, not perverted brain have difficulties to understand it)
      *grin*
      while (@adrs=(gethostent())[4]) { map { $\="\n";print join '.',unpack'C4',$_} @adrs }
      BTW I'm sure a Perl Guru, could tell me how to make this even smaller !
      Please show me the light !

      UPDATE
      Ooops ! I suddenly realized that even if MY /etc/hosts contains only entries about my local machine, it might not always be the case (in fact it should often contains entries about other machines...).
      So thousand apologizes, but all my posts in this thread do not resolve the problem...
      But my code could be use to get the ip adresses of the machines in /etc/hosts...
Re: How do I get the local internet IP address?
by Perlbotics (Archbishop) on Aug 13, 2008 at 22:31 UTC

    Sometimes, firewalls block a connection setup to a well known IP address. When using the resolve mechanisms it is assumed that the information — e.g. in /etc/hosts, name servers, etc. — is maintained, accessible, trusted, and valid.

    If both methods fail, a look at the actual IP configuration might help. As a (okay, maybe not the very) last resort, esp. when multiple interfaces and IPMP is concerned, examining the output of /sbin/ifconfig -a (*NIX), or ipconfig /all (WIN*) might work to reveal the interfaces currently plumbed and configured. At least the OS's tool which is responsible to configure the IPs should be able to give a reliable answer. The fragile part is to rely on the outputs layout.
    You might need to change the locale language (e.g. LANG, LC_ALL) beforehand.

    Illustrative code that was tested on Solaris 10, openSUSE 10.2, and OS X:
    #!/usr/bin/perl use strict; use Data::Dumper; my $interface; my %IPs; foreach ( qx{ (LC_ALL=C /sbin/ifconfig -a 2>&1) } ) { $interface = $1 if /^(\S+?):?\s/; next unless defined $interface; $IPs{$interface}->{STATE}=uc($1) if /\b(up|down)\b/i; $IPs{$interface}->{IP}=$1 if /inet\D+(\d+\.\d+\.\d+\.\d+)/i; } print Dumper(\%IPs); __END__ $VAR1 = { 'qfe0' => { 'IP' => '10.0.0.32', 'STATE' => 'UP' }, 'qfe1' => { 'IP' => '10.0.0.33', 'STATE' => 'UP' }, 'hme0' => { 'IP' => '10.0.0.14', 'STATE' => 'DOWN' }, 'lo0' => { 'IP' => '127.0.0.1', 'STATE' => 'UP' } };

        The OP code did work for me though on a closed box and Net::Address::IP::Local only seems to work if there is, as the method name suggests, a public address open otherwise it's Unable to create UDP socket: No route to host.... The OP code found the right address on both my running OS X boxes, one closed, one open.

      Update: I've ripped my code contribution out of this node and submitted it as a separate answer.

      I agree with the other posters that the best (as in portable and maintainable) solution would be to use a CPAN module.

      qx{ (LANG=C ; /sbin/ifconfig -a 2>&1) }

      I think it would be better to omit the ";" to make sure that the variable gets into the environment. Better yet would be to use "LC_ALL=C" because afaik that overrides all locales (including LANG).

      Hi all, thanks for your feedback. I also thought that LC_ALL is the 'right' way to do it because it has precedence over LANG, but when I tested it yesterday, only LANG did work. That's because LANG is automatically exported, LC_ALL not (on the machines available to me). So leaving the semicolon away made LC_ALL=C work. I'll update that, after testing it with the Solaris boxes.
      Actually, the regular expressions are so fuzzy, they match any language that is available on my installation (cs, de, et_EE, fr, pt_BR - the other 129 languages have no localisation for ifconfig (net-tools here)). Right this approach is not perfect, but I thought the phrases 'Sample' and 'last resort' made clear, that this is not production code and one might need to fiddle a bit around with it? Would you suggest to make that more explicit?

      The reason why I presented this sample was because it works for me and it shows another approach (TIMTOWTDI) that amend to the already given answers. If it works it works without the need to establish a connection and it lists all IPs, not only the one that leaves the (usually "default") route as when contacting a root name-server. This is handy if you're behind several layers of firewalls and in situations where you are interested in the local IP configuration.
      If the intention of the question is more like How do I get the local internet IP address that currently connects my host to the IP a.b.c.d? (which is often not identical with the IP address other hosts would contact the local machine in return), then I would prefer this suggestion from tirwhan. Also because it doesn't require to install a non standard module beforehand.

      Any other advice is appreciated. Thanks again.

Re: How do I get the local internet IP address?
by betterworld (Curate) on Aug 14, 2008 at 14:57 UTC

    This is probably the least portable version because it uses Linux-specific data structures, but for the fun of it and for completeness, I'll post it:

    #!/usr/bin/perl use strict; use warnings; require 'sys/ioctl.ph'; use Socket; my %interfaces; my $max_addrs = 30; socket(my $socket, AF_INET, SOCK_DGRAM, 0) or die "socket: $!"; { my $ifreqpack = 'a16a16'; my $buf = pack($ifreqpack, '', '') x $max_addrs; my $ifconf = pack('iP', length($buf), $buf); # This does the actual work ioctl($socket, SIOCGIFCONF(), $ifconf) or die "ioctl: $!"; my $len = unpack('iP', $ifconf); substr($buf, $len) = ''; %interfaces = unpack("($ifreqpack)*", $buf); unless (keys(%interfaces) < $max_addrs) { # Buffer was too small $max_addrs += 10; redo; } } for my $addr (values %interfaces) { $addr = inet_ntoa((sockaddr_in($addr))[1]); } use Data::Dumper; print Dumper \%interfaces;

    The output is:

    $VAR1 = { 'eth0:1' => '10.153.26.128', 'eth0' => 'x.y.z.128', 'eth0:3' => '10.153.84.128', 'eth0:4' => '10.153.88.2', 'eth0:2' => 'x.y.z.62', 'lo' => '127.0.0.1' };

    (I've stripped the public addresses.)

    I've successfully tested it on Debian etch and sarge.

      Works OK on Fedora 8 too.

      Krambambuli
Re: How do I get the local internet IP address?
by Anonymous Monk on Feb 09, 2001 at 19:54 UTC
    Same as above, but you can use this to resolve any address through the DNS setup (/etc/resolv.conf or the /etc/hosts file).

    use Socket; my $hostname = "somehost.ext"; my @addr = inet_aton($hostname) or return "Unknown or invalid host."; my($a,$b,$c,$d) = unpack('C4', $addr(0)); #change the $addr() to brackets, this form filters brackets out. my $ip = "$a.$b.$c.$d"; print $ip;
Re: How do I get the local internet IP address?
by AgentM (Curate) on Jan 24, 2001 at 02:01 UTC
    If you simply want to send yourself something, use the loopback address (127.0.0.1).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://53660]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2024-04-23 20:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found