meonkeys has asked for the wisdom of the Perl Monks concerning the following question:

My ISP changes my internet address every now and then (I have cable modem, eth0 gets an IP from the cable modem via DHCP). I want to detect when this happens, so I wrote a little program to persist the data and check if it has changed. This program is meant to be run by cron, and will probably email any output to me.

Is there an easier way to detect what internet address has been assigned to eth0? I tried to install Net::Interface (supposed to replace ifconfig), but it wouldn't compile.

Here's what I'm using now:

#!/usr/bin/perl -w use English; use strict; use vars qw( $INET_ADDR_FILE ); $INET_ADDR_FILE = "/home/adamm/.current_inet_addr"; die "only currently implemented for linux." unless ($OSNAME eq 'linux' +); ### MAIN my ($old_inet_addr, $found_old_addr_file) = read_saved_inet_addr(); my $new_inet_addr = read_new_inet_addr(); if (!$found_old_addr_file) { write_new_inet_addr($new_inet_addr); print "Current IP address ($new_inet_addr) stored to disk.\n"; } elsif ($old_inet_addr ne $new_inet_addr) { write_new_inet_addr($new_inet_addr); print <<OutputEnd; Change in IP address detected. New IP stored to disk. Old IP: $old_inet_addr New IP: $new_inet_addr OutputEnd } ### SUBS sub read_saved_inet_addr { my ($fh, $oldfile_found, $old_addr); open($fh, "< $INET_ADDR_FILE") ? $oldfile_found = 1 : warn "couldn't open $INET_ADDR_FILE. Hopefully this is the first + run.\n"; if ($oldfile_found) { $found_old_addr_file = 1; local $INPUT_RECORD_SEPARATOR = undef; $old_addr = <$fh>; $old_addr =~ s/\r|\n//; close($fh) or die "couldn't close $INET_ADDR_FILE"; } return ($old_addr, $oldfile_found); } sub read_new_inet_addr { local $INPUT_RECORD_SEPARATOR = undef; my $ifconfig_output = `/sbin/ifconfig eth0`; my ($new_inet_addr) = ($ifconfig_output =~ m/inet\saddr:(.+?)\s/); return $new_inet_addr; } sub write_new_inet_addr { my $new_addr = shift; my $fh; open($fh, "> $INET_ADDR_FILE") or die "couldn't create $INET_ADDR_FI +LE"; print $fh $new_addr,"\n"; close($fh) or die "couldn't close $INET_ADDR_FILE"; }


---
"A Jedi uses the Force for knowledge and defense, never for attack."

Replies are listed 'Best First'.
Re: Detecting when my ISP changes my IP
by BrowserUk (Patriarch) on Sep 22, 2002 at 05:51 UTC

    One way that is useful--especially if you have a local network connected to the net via a NAT box and your external IP is different to your local ip--is to parse it out of a request made to one of the zillions of "What is my IP" pages spread around the net. The address shown below is just the first one google turned up when I searched.

    (It would probably not be freindly of us if we all hit this one site. If you want to try this, feed the quoted string above into google, next page 2 or 3 times and then pick one. You might need to tweak the regex a bit.)

    #! perl -sw use strict; use LWP::UserAgent; my $ua = LWP::UserAgent->new; my $request = HTTP::Request->new('GET', 'http://www.internet-help.net/ +cgi-bin/ip-address.pl'); my $response = $ua->request($request); print $response->{_content} =~ m/(\d+\.\d+\.\d+\.\d+)/;

    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
Re: Detecting when my ISP changes my IP
by Kanji (Parson) on Sep 22, 2002 at 05:34 UTC

    You don't say why you need to detect an IP change, but there's been a few similar posts here in the monastery that might be worth checking out.

    Another option if you use ISC's dhclient, is to forego Perl altogether and make use of dhclient-script's exit hooks with an (untested!) shell script like...

    #!/bin/sh ## Script is sourced from dhclient-script. ## $reason and $new_ip_address are set there. if [ "X$reason" = "XBOUND" ]; then echo $new_ip_address > ~adamm/.current_inet_addr fi

        --k.


Re: Detecting when my ISP changes my IP
by gmpassos (Priest) on Sep 22, 2002 at 06:03 UTC
    Is use this way, but you need to declare a host for the machine, or you get 127.0.0.1:
    use Socket; use Sys::Hostname; my $host = hostname(); my $address = inet_ntoa(scalar gethostbyname($host || 'localhost')); print "$host > $address\n" ;
    For me this works on Linux and Win32, and I use a cable modem too.

    Graciliano M. P.
    "The creativity is the expression of the liberty".

Re: Detecting when my ISP changes my IP
by zengargoyle (Deacon) on Sep 22, 2002 at 07:05 UTC

    How about this?

    use IO::Socket::INET; $s = IO::Socket::INET->new ( PeerAddr =>"1.2.3.4", Proto =>"udp", ) or die "no socket!\n"; print $s->sockhost, " ", scalar(gethostbyaddr($s->sockaddr,$s->sockdomain)),"\n";
      That's more of an accidental feature than a reliable method. On machines with multiple network devices, it may bind from the wrong one. With a single network interface, there's simply no wrong interface to bind from.

      Makeshifts last the longest.

Re: Detecting when my ISP changes my IP
by Dr. Mu (Hermit) on Sep 23, 2002 at 06:19 UTC
    I had a similar requirement when my cable ISP switched to DHCP. Once, when the lease on my IP address expired, the system (RH Linux) requested a renewal from the DHCP server. When it was unable to access the server (ISP problems), it completely shut down eth1. Also, when the IP address changes, ntpd stops functioning and has to be restarted. So I wrote the following cron script (keepalive.pl) to stay connected and keep ntpd alive:
    #!/usr/bin/perl use strict; my $lastip; if (open IP, '</home/phil/usr/cron/lastip.dat') { $lastip = <IP>; chomp $lastip; close IP } else { print "**keepalive.pl** File 'lastip.dat' cannot be opened to read +: $!" } if (`netstat -i` =~ /eth1.*?inet addr:(\d+\.\d+\.\d+\.\d+)/s) { if ($1 ne $lastip) { print "**keepalive.pl**\n\n".`/etc/init.d/ntpd restart`; if (open IP, '>/home/phil/usr/cron/lastip.dat') { print IP "$1\n"; close IP } else { print "**keepalive.pl** File 'lastip.dat' cannot be opened + to write: $!" } } } else { print "**keepalive.pl**\n\n".`/etc/init.d/network restart` }
    The script runs every five minutes. In the event that eth1 has been dropped, it restarts network, then on the next go 'round restarts nptd if the IP has changed. Maybe there will be something of value in there for you.

    There's also a companion cron script (ddclient, a free perl script I downloaded) that keeps separate tabs on my IP address and keeps my dyndns entry up-to-date. ddclient uses a remote IP echoing server to obtain the address -- but, of course, fails when eth1 is killed.