#!/usr/bin/env perl
# @(#) DtDNS.pl  Update client for www.dtdns.com; performs Dynamic
#                DNS updates as requested. Rev'd: 2014-06-24.
#
# Copyright (c) 2013 Graham Jenkins <grahjenk@cpan.org>. All rights reserved.
# This program is free software; you can redistribute it and/or modify it under
# the same terms as Perl itself.

use strict;
use warnings;
use File::Basename;
use LWP::Simple;
use vars qw($VERSION);
$VERSION = "1.07";

# Check usage, open configuration file
my ($Conn,$Minutes)=("https",);
if ( ($#ARGV >= 0) && ($ARGV[0] eq "-u"    ) ) { $Conn="http"; shift}
if ( ($#ARGV == 1) && ($ARGV[0] =~ m/^\d+$/) ) { $Minutes=shift }
if ( $#ARGV != 0 ) {
  die "Usage: ".basename($0)." [repeat-interval] config-file\n".
      " e.g.: ".basename($0)." 30 /usr/local/etc/DtDNS.conf\n"
}
if ( ! open(CF,$ARGV[0]) ) { die "Can't read file: ".$ARGV[0]."\n" }

# Read and store valid records, then close the file
my %Pass;
while (<CF>) {
  chomp;
  if ( length() < 2 ) { next }
  my ($Line)=split;
  my ($h,$p) = split /:/, $Line;
  if ( defined($p) && ($h !~ /\043/) ) { $Pass{$h}=$p }
}
close(CF);
if ( keys(%Pass) < 1 ) { die "No valid records found in file: ".$ARGV[0]."\n" }

# Use Syslog if we can
my $rc=eval { require Sys::Syslog; Sys::Syslog->import(); 1 };
if ($rc) { openlog(basename($0),"","user") }
else     { sub syslog {}                   }
 
# Assemble the client name, force an address update on first pass, enter loop
my ($ClNm,$OldAddr,$ChangeTime,$Status)=(basename($0)."-".$VERSION,"x",0,-1); 
while (1) {
  # Get current address
  if( defined(my $Address=get("http://myip.dtdns.com")) ) {
    chomp ($Address);
    syslog("info","Vers: $VERSION. Current address is: $Address");
    # Update each host record on first pass or if current address changed
    if ( $Address ne $OldAddr ) {
      foreach my $h ( keys(%Pass) ) {
        syslog("info","Attempting update for $h");
        my $p=$Pass{$h};
        if( defined(my $Response=get(
          "$Conn://www.dtdns.com/api/autodns.cfm?id=$h&pw=$p&client=$ClNm")) ){
          syslog("info",$Response);
          if( $Response=~m/now points/ ) {
            $OldAddr=$Address; $ChangeTime=time(); $Status=0
          }
        }
        else { syslog("info","No response from server!") }
      }
    }
  }
  else { syslog("info","Vers: $VERSION. Unable to determine current address!")}
  if ( defined($Minutes) ) {sleep(60*$Minutes)}
  else                     {exit($Status)     }
  # Force an address update on next pass if there hasn't been one for 7 days
  if ( ( time() - $ChangeTime ) > 7*24*3600 ) { $OldAddr="x" }
}

__END__

=head1 NAME

DtDNS - update client for www.dtdns.com

=head1 README

DtDNS will update one or more designated DNS records at
www.dtdns.com either once or periodically.

=head1 DESCRIPTION

C<DtDNS> is a simple update client for the DtDNS dynamic
DNS service. It will attempt an immediate update when called,
then optionally loop at designated intervals, attempting 
further updates when necessary.

=head1 USAGE

=over 6

DtDNS [-u] [repeat-interval] config-file

=back

e.g.: DtDNS 30 /usr/local/etc/DtDNS.conf

The repeat-interval value (where present) must be
expressed as a positive integer number of minutes.
If the '-u' flag is included, then an unsecure (http)
connection will be used.

The config-file value must be the name of a configuration
file which contains one or more hostname:password records
where each password relates to the owner of the
corresponding hostname. Each record should appear on a
separate line thus:

  lassie.dtdns.net:secret1
  fido.etowns.org:secret2
   .. etc.


It is suggested that the configuration file should be
readable only by the intended program-user.
I<Sys::Syslog> will be used for logging if it's installed;
you might want to check your system's syslog configuration so
that you can view log messages.

=head1 NOTE

By default DtDNS uses a secure (https) connection. For this to
work, you need to ensure that I<LWP::Protocol::https> is installed.

=head1 SCRIPT CATEGORIES

Networking
UNIX/System_administration

=head1 AUTHOR

Graham Jenkins <grahjenk@cpan.org>

=head1 COPYRIGHT

Copyright (c) 2013 Graham Jenkins. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

=cut
