http://qs1969.pair.com?node_id=127997
Category: Networking Code
Author/Contact Info ybiC
Description: One of my boxen is dial-connected nailed up using /etc/ppp/ppp_on_boot plus persist and holdoff parameters in /etc/ppp/peers/provider.   Whenever the connection is (re)established, this ditty sends the new ppp0 IP address to my dynamic DNS provider.

Not much of a Perlish exercise, but was fun to make practical use of new (to me anyways) IO::Interface.

Start dynamic DNS update:

Check ppp0 status: ACTIVE
Query host for ppp0 address: PASS
Post ppp0 IP address to DynDNS service: PASS
Check DNS propagation via name lookup: PASS
Compare resolved address to local: PASS
  nnn.nnn.nnn.nnn <= my.host.com
  nnn.nnn.nnn.nnn <= ppp0

Finished dynamic DNS update
#!/usr/bin/perl -w

# ddns.pl
# pod at tail


$|++;
use strict;
use IO::Socket;
use IO::Interface;
use HTTP::Request::Common qw(POST);
use LWP::UserAgent;

my $id   = '';
my $pass = '';
my $site = '';
my $fqdn = '';
my $if   = 'ppp0';


print "\n";
print "Start dynamic DNS update for $fqdn:\n";
print "\n";
my $s = IO::Socket::INET->new(Proto => 'udp');
my @interfaces = $s->if_list;


print "Check $if status: ";
my $ifup = 0;
for(@interfaces){
  $ifup++ if( $_ =~/$if/ );
}
if($ifup == 0){
  print "INACTIVE - ABORT\n\n";
  exit 0;
}
print "ACTIVE\n";


print "Query host for $if address: ";
my $addr;
if($addr = $s->if_addr($if)) { print "PASS\n"; }
else { print "FAIL:\n$!"; }


print "Post $if IP address to DynDNS service: ";
my $ua = LWP::UserAgent->new();
$ua->credentials($id, $pass);
my $request = POST "$site", [ip => $addr, action => 'update'];
$request->authorization_basic($id, $pass);
my $response = $ua->request($request);
if ($response->is_success) {
  print "PASS\n";
} else {
  print "FAIL:\n", $response-> message, "\n";
  exit 0;
}


print "Check DNS propagation via name lookup: ";
my $packed_address = gethostbyname($fqdn);
unless ($packed_address) {
  print "FAIL:\n $!";
  exit 0;
}
print "PASS\n";


print "Compare resolved address to local: ";
my $dotted_quad = inet_ntoa($packed_address);
if($dotted_quad eq $addr){
  print "PASS\n";
} else {
  print "FAIL:\n$!";
  exit 0;
}
print "  $dotted_quad <= $fqdn\n";
print "  $addr <= $if\n";

print "\n";
print "Finished dynamic DNS update for $fqdn:\n\n";


exit 1;


######################################################################
+#####

=head1 NAME

ddns.pl

=head1 DESCRIPTION

Update dynamicDNS service for computer on dial-up connection.

=head1 USAGE

 Accepts no arguments.

 Create symlink in /etc/ppp/ip-up.d/ so will be
 called whenever dial-up connection is (re)establised:
   ln -isv /path/to/ddns.pl /etc/ip-up.d/ddns

 Works well in conjuntion with /etc/ppp/peers/provider 'persist' and
 'holdoff' parameters plus /etc/ppp/ppp_on_boot for nailed-up connecti
+on.


=head1 REQUIREMENTS

 perl 5
 libwww-perl
 IO::Interface
 make to install modules
 gcc   "   "       "
 libc6-dev "       "
 /etc/nsswitch => hosts: dns files
   so name confirm is from DNS not /etc/hosts.

=head1 UPDATE

 November 27, 2001   20:20 CST
   Compare local interface IP address with DNS lookup address.
   Check for interface active before proceeding.
   Confirm DNS updated correct IP address with gethostbyname().
   Use IO::Socket+Interface to determine local ppp0 IP address
     instead of ifconfig with backticks.
   Eliminate (unecessary) subroutines.

 October 27, 1999
   Initial working code.

=head1 CREDITS

 jwest for nsswitch, libc6-dev tips
 vroom for PerlMonks

=head1 AUTHOR

ybiC

=cut