pax_global_header00006660000000000000000000000064117036245040014514gustar00rootroot0000000000000052 comment=1382a81dbf4b2d5cddd412e9993a98fba8b46ef6 dyndns-2012.0112/000077500000000000000000000000001170362450400133235ustar00rootroot00000000000000dyndns-2012.0112/ChangeLog000066400000000000000000001013561170362450400151030ustar00rootroot000000000000002011-12-10 Sat Jari Aalto * Makefile: Mnor variable updates. 2011-11-03 Thu Jari Aalto * bin/dyndns.pl Remove Emacs folding.el marks. (TestMain): New. (TestDriver): Add German test case. (GetIpAddressWin32): Modify $base regexp to support German ifconfig(1) 2011-09-27 Tue Jari Aalto * Makefile: Adjust comment for 'make help'. 2010-10-25 Tue Jari Aalto * bin/dyndns.pl (HELP): Adjust wording. 2010-10-11 Mon Jari Aalto * Makefile (PERL): New variable. * bin/dyndns.pl (HELP): Document that --file-default is default setting unless --file is given. (HandleCommandLineArgsMain): Activate ipfileDefault unless OPT_IP_FILE is not set. Debian bug #593255. (GetIpAddressIfconfig): Improve regexp to work with pt_BR locale. Debian Bug #593253. (Help): rewrite 'Pod::Man module load. 2010-06-14 Mon Jari Aalto * bin/dyndns.pl (StringMatch): Add $LIB to $id variable. 2010-05-21 Fri Jari Aalto * bin/dyndns.pl (InitializeModules): (HELP): Remove duplicate section AVAILABILITY. 2010-05-01 Sat Jari Aalto * bin/dyndns.pl (HandleCommandLineArgs): Remove "require_order" from Getopt::Long::config(). 2010-04-15 Thu Jari Aalto * bin/dyndns.pl (Help): Fix Perl 5.10 bug in pod2text(). (Help): rewrite eval Pod::Man call. 2010-03-13 Sat Jari Aalto * bin/dyndns.pl (top level): rearrange globals, use comamnds. (Version*): new. 2010-03-12 Sat Jari Aalto * bin/dyndns.pl: (top level): English qw( -no_match_vars ) 2010-03-02 Tue Jari Aalto * bin/dyndns.pl (Help::EXAMPLES): Add crontab(5) entry. * Makefile (dist-git): Run 'test'. (dist-snap): Run 'test'. * INSTALL (INSTALL): Correct crontab explanation. 2010-03-01 Mon Jari Aalto * INSTALL: Update requirements and manual install. * bin/dyndns.pl (top level): Update copyright template. (HandleCommandLineArgsMain): Change all options to use lowercase names: instead of --Version, use --version etc. (Help): Document that --provider option supports only dyndns at this time. (Initialize): Add AUTHOR, URL, LICENSE. 2009-03-18 Jari Aalto * dyndns.pl (top level, Help): Copyright year update. (top level): Adjust required modules comments at the beginning. 2008-11-11 Jari Aalto RELEASE: 2008.1111 * dyndns.pl (VariableCheckMinimum): Add local 'no strict' to fix variable use error with Perl 5.10.0. (HELP::ENVIRONMENT): Document TMPDIR. (TempDir): Use TMPDIR. Remove TEMP. (LogSyslog): Check if syslog is available. If not, use stderr. (top level): add @REQUIRE_FATAL, @REQUIRE_OPTIONAL, @FEATURE_LIST_MODULES. (InitializeModules): Check @REQUIRE_FATAL, @REQUIRE_OPTIONAL and set @FEATURE_LIST_MODULES. 2008-08-12 Jari Aalto * dyndns.pl (ConfigFileRead): Change 'no strict' to more detailed no strict 'refs'. 2008-03-22 Jari Aalto * dyndns.pl (Log): Add newline to the end if not in MSG. 2007-11-16 Jari Aalto * dyndns.pl (ProcessUpdateOne): Display message only if the update is tried in less than a day. 2007-10-24 Jari Aalto * dyndns.pl (StatusCodeHandle): Fixed few debugging messages. 2007-10-01 Jari Aalto * dyndns.pl (InitializeModules): New. Moved CPAN module 'use' commands to separate function to notify user; closes bug https://sourceforge.net/tracker/index.php?func=detail&aid=1038122&group_id=44223&atid=438824 (TestDriverLinksysBEFW11S4v4): Cisco v4 versio test. (HttpPingWlanLinksysBEFW11S4): Add BEFW11S4 Cisco v4 support; closes bug https://sourceforge.net/tracker/index.php?func=detail&aid=1152587&group_id=44223&atid=438824 (RunUpdateIPWrite): Report invalid Ip address to syslog. (UpdateDynDns): Run IPvalidate before update. (UpdateHNorg): Run IPvalidate before update. (UpdateNoip): Run IPvalidate before update. 2006-09-06 root * dyndns.pl (SystemLogDir): Added check for non-root user. The saved ip is put under $HOME/tmp. (IPfileNamePath): Renamed. Was `IPfileName'. 2006-08-30 Jari Aalto * dyndns.pl (Initialize): (Help::PREREQUISITES): added 'LWP' to list of required modules from CPAN. (HttpPingDyndns): Added parameter LOGIN. (HttpPingWlanLinksysWRT54GL): New. (GetIpAddress): Added support for WRT54GL. (HandleCommandLineArgsMain): Changed command line option --urlping-linksys4 to --urlping-linksys TYPE, where TYPE is model code of product. (TestDriverLinksysWRT54GL): New. 2006-02-03 Jari Aalto * dyndns.pl (HandleCommandLineArgsMain): Typo in variable: $t2htmlOPT_IP_FILE => $OPT_IP_FILE. 2005-11-30 Wed Jari Aalto * dyndns.pl (sub Version): 1.125 New. (sub VersionInfo): 1.125 New. (sub Main): 1.125 if debug is on, print version information. (sub HandleCommandLineArgsMain): 1.125 Added 'OPT_DAEMON', OPT_ETHERNET, OPT_PROXY variable to @CONFIG_COMMAND_LINE_TABLE, so that --Daemon option setting is preserved even if configuration file does not define it. Bug reported by Thomas Gutzler (sub main): 1.125 Added loop debug message. Removed else-statement (Added 'next') (sub UpdateDynDns): 1.125 Under --test mode show that this is test from messages. (HELP::OPTIONS::--Daemon): Explain why it is better to use cron(8) than use --Daemon option. 2005-11-24 Jari Aalto * dyndns.pl (HELP::OPTIONS::--Config): Corrected wording and removed conf.d/ reference. dyndns.pl (HELP::OPTIONS::--login): Removed word 'Your'. dyndns.pl (HELP::OPTIONS::--password): Removed word 'Your'. dyndns.pl (HELP::OPTIONS::--system): Added {}'s to indicate that one of the items is required. dyndns.pl (HELP::OPTIONS::--Daemon): Grammar fixes. Added new chaper to talk about system resources and Perl language. dyndns.pl (HELP::OPTIONS::--ethernet): Added []. The parameter is optional. dyndns.pl (HELP::OPTIONS::--Query): Grammar fixes dyndns.pl (HELP::OPTIONS::Cable, DSL and router options): Added NOTE to warn about HTML tags. dyndns.pl (HELP::OPTIONS::--urlping): Added warning about --Daemon mode. 2005-05-16 Mon Jari Aalto * dyndns.pl - command line arguments --urlping-* were not preserved, but cleared when reading configuration files. (sub ConfigFileProcess): 1.122 Parameters are now passed in HASH, instead of @ARG. Added parameter -global. (sub ConfigFileRead): 1.122 Added %global to record user given command line arguments. (sub HandleCommandLineArgsMain): 1.122 Added @CONFIG_COMMAND_LINE_TABLE. 2005-02-27 Sun Jari Aalto * dyndns.pl (sub GetIpAddress): 1.121 Wrong variable passed to `HttpPingWlanLinksysBEFW11S4'. Did not send password. Fixed. 2005-02-15 Tue Jari Aalto * dyndns.pl (sub ProcessQueryRequests): 1.117 Changed output format. Added IP address in case of changed. (Getopt::Long): 1.117 Corrected OPT_QUERY_IP_CHANGED bug, which caused script to always complain about missing --Host even with update requests. (sub HandleCommandLineArgsMain::%CONFIG_FILE_MAP_TABLE): 1.117 Added new user option `disable' to make the configuration file disabled. (Help::CONFIGURATION FILE): Documented new option `disable'. (sub HandleCommandLineArgsMain): 1.117 New global `$OPT_IGNORE_CONFIG'. (sub ConfigFileRead): 1.117 Added check for new `disable' option in configuration file. (sub Initialize): 1.117 Small changes to texts in `%STATUS_CODE_NOIP_HASH'. Confirmed that they are still the same as in official noip-2.1.1 C-source. 2005-01-19 Wed Jari * dyndns.pl (Getopt::Long): 1.117 Require --Host option for queries, because the file name cannot be constructed otherwise. 2004-12-19 Sun Jari * dyndns.pl (sub ProcessUpdateOne): 1.117 Added missing newline to 'It is not allowed ...' message. 2004-08-13 Fri Jari Aalto * dyndns.pl (Bad authorization): 1.116 Added more tests to HN site. 2004-05-29 Tue Jari Aalto * dyndns.pl (StatusCodeParseHNorg(): The regexp must look access lines for the status code. Didn't work. Fixed by adding modifier 'm' and removed split(). (TestDriverHNorg): New (RunUpdate): Change hn.org => dup.hn.org (FileWrite): Added $test check. Do not write in test mode. (UpdateHNorg): Wrong parameter send to StatusCodeHandle(). Changed -noip => -hnorg (StatusCodeHandle); Lacked 'hnorg' handling. Added. (Initialize): Wrong url 'foge' => 'forge'. Fixes SF bug#849488 (HandleCommandLineArgsMain): Added better debug message for --Daemon option. 2004-03-30 Tue Jari Aalto * dyndns.pl CHANGE: The IP file cannot be simply eth0-dyndns-dyndns.log, because it won't tell how many hosts for 'dyndns' type were updated. Suppose host A is updated in class 'dyndns' at dyndns.org, then host B is updated at the same class later on. Program would check if class 'dyndns' IP file exists and would deny updating host B, because it thinked value haven't changed. This was because, it didn't differentiate between host A and host B, which both are in class 'dyndns'. They can be updated separately. New naming scheme now uses eth0-dyndns-dyndns-HOST.log files to store IP. (sub IPfileName): 1.114 Added HOST to the ip file name. (sub IPfileName): 1.114 Rewrote how the IP filename was made. (sub ProcessUpdateStart): 1.114 Send @OPT_HOST to IPfileName(). (sub ProcessQueryRequests): 1.114 Send @OPT_HOST to IPfileName(). (SystemLogDir): 1.114 Added more checks for windows and 'else' to PANIC or fatal error. (top level): 1.114 Added $TEMPDIR. (sub TempDir): 1.114 Added TEMPDIR and Panic test for not finding temporary directory. (sub Initialize): 1.114 Under Linux, always set PATH to include basic system directories. (sub TimeValue): 1.114 New. (Help): 1.114 --daemon option now accepts 2d, 7h; days, hours spec. 2004-03-26 Jari Aalto * dyndns.pl (HandleCommandLineArgsMain): Improved --Test-account handling. Added custom dns test. 2004-03-26 Fri Jari Aalto * dyndns.pl (Sys::Syslog'): 1.113 Made Sys::Syslog `autouse'. (HELP::FILES): Documented C:/syslog.txt. 2003-12-13 Sat Jari Aalto * dyndns.pl: 1.112 (Help): Documentation typos fixed. 2003-09-02 Tue Jari Aalto RELEASED 2003.0902 * dyndns.pl (IPfileNameGlobbed): 1.108 Added note, that user should give option --file-default (VariableCheckMinimum): 1.108 Variable check incorrect. Always failed to see content of the configuration variables. This practically made configuration files useless. Added new `eval'. (UpdateDynDns): 1.109 Added HTTP headers `Pragma' and `Connection' (UpdateNoip): 1.109 Added HTTP headers `Pragma' and `Connection' (UpdateHNorg): 1.109 New. (HTTPheaderSet): 1.109 New. Common headers for all HTTP requests. 2003-08-22 Fri Jari Aalto * dyndns.pl (sub IPfileNameGlobbed): 1.107 Added check for not defined OPT_IP_FILE. (sub ProcessQueryRequests): 1.107 Added Check of file is old => consider IP changed. (sub IsFileOlderThanDays): 1.107 Now returns two values instead of one. (sub ProcessQueryRequests): 1.107 Added new feature. Now outputs DAYS since last update. See documentation of option --Query-ipchanged. (sub VariableCheckValidity): 1.107 Removed enabling OPT_QUERY automatically if OPT_HTTP_PING_LINKSYS4 or OPT_HTTP_PING_DYNDNS were given at command line. Use must request Explicit --Query-* features. 2003-08-08 Fri Jari Aalto * dyndns.pl (elsif (GetIpAddress): Missing semicolon fixed. (Top Level): 1.105 Added lot of Log() function calls. These should improve the --deamon and syslog(3) usage. 2003-08-06 Wed Jari Aalto * dyndns.pl: 1.100 (Help): New option --urlping-dyndns. (sub VariableCheckValidity): 1.100 Added OPT_HTTP_PING_DYNDNS (sub GetIpAddress): 1.100 Added OPT_HTTP_PING_DYNDNS (sub HttpPingDyndns): 1.100 New. (sub IPvalidate): 1.100 Added 0.0.0.0 test. (LWP::UserAgent): Do not connect in test mode. (sub VariableCheckValidity): 1.101 Automatically add --Query option if --urlping-* option is set. User does not need to supply --Query explicitly eny more. (sub FileWrite): 1.102 Added 3rd parameter to call list: APPEND. (sub FileRead): 1.102 New. (sub ConfigFileRead): 1.102 Use FileRead(). (sub LogSyslog): 1.102 Now works under Cygwin. The log appear in Windows event log (application). (sub TestDriverSyslogUnix()): 1.103 New. (sub TestDriverSyslogWin32()): 1.103 New. (sub TestDriverSyslogWin32native()): 1.103 New. (sub TestDriverSyslogWin32cygwin()): 1.103 New. (sub LogSyslog): 1.103 Added better debug messages. Verified functionality in Debian unstable / kernel 2.2. Messages appeared correctly in /var/log/daemon.log (Help:SEE ALSO): Added entries. 2003-08-05 Tue Jari Aalto RELEASED: 2003.0805. The new configuration file implementation had numerous errors. This fixes those and adds initial support to syslog(3). * dyndns.pl (sub LogSyslog): 1.98 Disabled function, not yet tested. (HELP): FILES section /etc/dyndns documentation added. 2003-08-04 Mon Jari Aalto * dyndns.pl: (Help) 1.84 Corrected documentation of options --Query and --Query-ipfile. (Getopt::Long): 1.84 Options --file-default mistakenly toos additional string argument '=s'. Removed. (sub ProcessUpdateMain): 1.84 Called glob unnecessarily. Moved logic to local function ProcessIt(). (sub Initialize): 1.84 Added global varibale $CYGWIN. (sub SystemLogDir): 1.84 Pushed /var/log test first. Cygwin perl fix. (sub SystemLogDir): 1.84 Convert path to forward slashes. (Help:CONFIGURATION FILE): Added new key=value [file=default], which corresponds to --file-default. (Help:LINUX CONTROL SCRIPT): Added note that this section is obsolete. It will be replaced soon. (sub ProcessQueryOptions): 1.84 Added debug messages. (sub IPfileNameGlobbed): 1.84 New. (sub HandleCommandLineArgsMain): 1.84 Fixed option --debug to take no argument (level) to activate debug. (sub SystemLogDir): 1.85 Added safety measures against non existing system directory and unknown OS layout. Fall back to to use TempDir(). (sub TempDir): 1.85 New. (sub ConfigFileProcess): 1.85 Added support for setting file=default. (Help:AVAILABILITY): Wrong url pointed to sourcefoge project. Fixed. (Top Level): Fixed Emacs folding.el '{{{' => '# {{{'. (sub IPfileName): 1.86 If-statement inaccurate: Check ARG and ABS, not just ABS. There is nothing to do if ARG is empty. (sub Main): 1.86 Added debug. (sub HandleCommandLineArgsMain): 1.86 Debug section for ARGV fixed. (sub ProcessUpdateMain): 1.86 Removed unnecessary logic and moved it to ProcessUpdateMaybe(). This was due to --Query option which did not work unless given option --file-default. It does not need that option in order to function. (sub ProcessUpdateMaybe): 1.86 Rewritten. Bad logic. (sub ProcessQueryOptions): 1.86 Removed input parameters $ip and $lastIP. They cannot be passed to function. Find those out independently. (Getopt::Long): 1.86 OPT_QUERY_IP_CHANGED now takes optional argument. (sub ProcessQueryOptions): 1.86 Support for OPT_QUERY_IP_CHANGED added. (Help): New option --Query-ipchanged. (sub ProcessQueryOptions): 1.86 Added local subroutine DefineVars(). (sub GetIpAddressGenericParser): 1.86 Added more debug. (Getopt::Long): 1.88 Added more checks for option --Query-ipchanged. (sub ProcessQueryOptions): 1.88 Bugs in handling option OPT_QUERY_IP_CHANGED. Dind't set $quit status. (sub VariableCheckValidity): 1.88 Added optional function parameter FILE. (sub ProcessUpdateMain): 1.88 Send configuration filename to VariableCheckValidity(). (sub ProcessUpdateMaybe): 1.88 Missing call to IPfileName() added. (sub ProcessQueryOptions): 1.88 Added IPvalidate() to OPT_QUERY_IP_CHANGED check. A 192.* 10.* addresses should not be compared and reported as a 'change'. (sub ProcessUpdateStart): 1.92 Rewrote. (sub ProcessUpdateStart): 1.92 Call VariableCheckMinimum() to check variables. (sub VariableCheckMinimum): 1.92 New. (sub HandleCommandLineArgsMain): 1.92 New variable @REQUIRED_UPDATE_OPTION_LIST. (sub Log): 1.95 New. (sub LogSyslog): 1.95 New. 2003-08-03 Sun Jari Aalto RELEASED: 2003.0803 * dyndns.pl -- NOTE: varibale DYNDNS_PL_CFG is no longer used. It is replaced by option --file. (sub RunUpdate): 1.71 Added 2nd return parameter: MSG. This is explanation of the error in case update failed and new try can be done. (sub WriteIpAddress): 1.71 Added return value if write was ok. (sub RunUpdateIPWrite): 1.71 Added return value if write was ok. (sub ProcessUpdate): 1.71 RunUpdate() returns 2nd value. Take that, $msg, and print to. New: Return 3 values from functions. (sub UpdateDynDns): 1.71 Added 2nd return value, error message's STR. (sub UpdateNoip): 1.71 Added 2nd return value, error message's STR. (sub StatusCodeHandle): 1.72 Added `else' for unknown providers whose error codes are not in the program. (sub IPvalidate): 1.74 Added more verbose --debug putput. (sub ProcessUpdate): 1.74 Added INPUT debug message. (sub HandleCommandLineArgs): 1.74 More accurate DYNDNS_PL_CFG filename creation to allow it to be plain E.g. 'directory/' (sub SystemLogDir): 1.75 New. (sub IPfileName): 1.76 New. (sub ConfigFileRead): 1.76 New. (sub ConfigFileParse): 1.76 New. (sub ConfigFileProcess): 1.76 New. (Help::BUGS): Added information how to contact the maintainer in case of adding new OS support. (Help): Moved all options to alphabetical order. (Help::CONFIGURATION FILE): New section added. (Help:--file): explained saved ip file creations. (sub FileWrite): 1.76 Renamed. Was `WriteIpAddress'. (sub FileWriteCheck): 1.76 New. (sub ProcessUpdateMain): 1.77 New. Handle multiple configurations files. (sub FileWriteCheckIP): 1.77 New. (sub ProcessQueryOptions): 1.77 New. (sub ProcessUpdateMaybe): 1.77 New. (sub HandleCommandLineArgsValidity): 1.77 New. (sub ConfigFileRead): 1.84 Do not use glob() if file already exists. Gnob returns undef in that case. (sub ProcessUpdateMain): 1.84 Use local function ProcessIt() in order to not use duplicate code. 2003-08-02 Sat Jari Aalto * dyndns.pl (sub ProcessUpdate): 1.64 Added ID string + [WARN] to message 'Hm, update failed...' (sub UpdateDynDns): 1.64 Added $debug to print input parameters. (sub StatusCodeHandle): 1.64 Added debug to print @list. (sub ProcessUpdate): 1.67 Do not `die' but `warn' if same IP was updated. This is needed to keep --Daemon mode active. 2003-07-31 Thu Jari Aalto * dyndns.pl: 1.63 (Help): Minor documentation changes. (sub HandleCommandLineArgs): 1.63 Added option --file to save IP to a user defined file. Added option --Query-ipfile. (Help): 1.63 Documented option --file and --Query-ipfile and updated section ENVIRONMENT. (sub Main): 1.63 Chnaged logic to honor multiple --Query options. Now exit, when OPT_QUIT is raised. 2003-07-29 Tue Jari Aalto * dyndns.pl (sub Main): 1.60 The FILE now contains portion pf the --system option, so that static and dynamic updates are saved to different files. That's because they have different update times. 2003-07-26 Sat Jari Aalto * dyndns.pl (sub HandleCommandLineArgs): 1.56 --system option missing the `s' Getopt::Long directive, so it dind't accept `statdns'. (syb UpdateDynDns): 1.56 Return LIST: status code and explanation. (sub UpdateNoip): 1.56 Return LIST: status code and explanation. (sub RunUpdate): 1.56 Return LIST: status code and explanation. (sub Initialize): 1.56 New @STATUS_CODE_DYNDNS_TRY_AGAIN and @STATUS_CODE_NOIP_TRY_AGAIN (sub StatusCodeHandle): 1.56 Function taken into use. Previously did nothing. Examine if the status codes are fatal or non-fatal (so that you can try update again). (sub ProcessUpdate): 1.56 Added check for failed or successful ip update. Instruct user to try again if the error is not fatal. (sub Main): 1.56 The IP address is now saved to a file ending to `.log'. 2003-07-22 Tue Jari Aalto * dyndns.pl (sub GetIpAddressInfo): 1.54 Changed return value. Now returns LIST, instead of string. (ProcessUpdate): 1.54 New. Added check for changed IP address, not just check for over 3 days. Bug reported by Jack Repenning . (main): 1.54 Moved logic to ProcessUpdate(). 2003-07-21 Mon Jari Aalto * dyndns.pl (sub Main): 1.53 Added support for multiple network cards. Save IP address with ifconfig prefix (ppp0, ppp1; $HOME/config/dyndns.pl.conf-ppp0-dyndns) etc. Patch sent by Juha Heljoranta 2003-05-10 Sat Jari Aalto RELEASED: 2003.0510 * debian/control: Correct package name from perl_dyndns => perl-dyndns * admin.bashrc (function sfperldyn_ReleaseDebian ()): 1.12 Improved error checking. Tested the environment under Win32/Cygwin (debian tools are included in it). The .deb packaging has not been tested at live installation. 2003-04-26 Sat Jari Aalto * dyndns.pl Improved that IP address check in this version. Allow same IP address updates, if at least 3 days has been passed. This may be useful to ISDN/modem users who have just swithced to a ADSL and Cable modem, but whom still use the dynamic DNS account. This is a transitions phase to start using the static DNS (dyndns.org) because the ADSL/CABLE ip-address do not change so often. (sub Date): 1.49 New. (sub DateDiffDays): 1.49 New. (sub FileDate): 1.49 New. (sub IsFileOlderThanDays): 1.49 New. (sub Main): 1.49 Added Call to `IsFileOlderThanDays'; check for 3 days. Die with warning 'same IP must not be updated multiple times' if the update happes faster than every 4 days. (sub RunUpdateIPWrite): 1.49 New. (sub WriteIpAddress): 1.49 Changed `die' to `warn'. 2003-03-01 Sat Jari Aalto * admin.bashrc (function sfperldyn_doc ()): 1.5 Added generating text docs. 2003-02-28 Fri root * admin.bashrc (function sfperldyn_VersionUpdate ()): 1.5 New. (function sfperldyn_IsDebian ()): 1.5 New. (function sfperldyn_MakeFilename ()): 1.5 New. (function sfperldyn_version ()): 1.5 New. (function sfperldyn_DebianControlGetVersion ()): 1.5 New. (function sfperldyn_DebianControlGetVersionNew ()): 1.5 New. (function sfperldyn_DebianControl ()): 1.5 New. (function sfperldyn_ReleaseDebian ()): 1.5 New. (function sfperldyn_release ()): 1.5 Call `sfperldyn_ReleaseDebian'. * dyndns.pl - Removed #!/usr/local/bin/perl and used plain #!perl (HandleCommandLineArgs): 1.47 Moved environment variable DYNDNS_PL_CFG test here. Program couldn't be run with plain --Version options. Fixed. (HandleCommandLineArgs): 1.47 Version information was not printed to stdout. Fixed. (Help): 1.47 Options are now --Help-man and --Help-html, not --help-man (lowercase) 2003-02-26 Wed Jari Aalto * admin.bashrc Added GPL to the beginning. (function sfperldyn_release_check ()): 1.5 New. (function sfperldyn_release ()): 1.5 Call `sfperldyn_release_check' before making release. (function sfperldyn_ask ()): 1.5 New. * dyndns.pl: Incorrect --version => --Version fixed in all functions. (GetIpAddressLast): 1.42 Added error checking: if FILE parameter is empty. (GetIpAddressInfo): 1.42 Changed input arguments from LIST to a HASH. Added parameter -query. (Help): 1.42 Added option --Query. Updated LINUX CONTROL SCRIPT. Changed minimum daemon time from 15 to 3 minutes. (Initialize): 1.42 Added $OPT_QUERY (Main): 1.42 Added $OPT_QUERY handling. (Main): 1.42 Removed OPT_HTTP_PING and OPT_HTTP_PING_LINKSYS4. They do not belong here. (GetIpAddress): 1.42 Added OPT_HTTP_PING and OPT_HTTP_PING_LINKSYS4. (HandleCommandLineArgs): 1.44 Added options --urlping-login and --urlping-password. Generic options to log into any web page. (HttpPing): 1.44 Changed arguments from LIST to HASH. Added option -login and -pass (Help): 1.44 Documented new options --urlping-password and --urlping-login (HttpUrlMake): 1.44 New. (HandleCommandLineArgs): 1.44 Improved defualt regexp to also detect cable and DSL router's WAN information. (Help): 1.44 Documented new options --urlping-password and --urlping-login (HttpUrlMake): 1.44 New. 2003-02-22 Jari Aalto * dyndns.pl (HandleCommandLineArgs): Do not require Minimum options when running in --test mode. (HttpPing): Too restrictive http:// regexp check opened. The format now allows username and password in the URL. (HttpPing): Removed the TEST check. Allow sending httpping, when --test option is set. (HttpPingWlanLinkSysBEFW11S4): New. (HandleCommandLineArgs): Added option --urlping-linksys4 Added support for 'Wireless AP Router w/4 port Switch'. See http://www.linksys.com/ (TestDriverLinksys4): New. (GetIpAddressWin32): Added support for LAN ip address. (IPvalidate): New. Internal ranges 192.* and 10.* are not valid and should not be allowed to update. (Main): Added safeguard agains invalid IP addresses. 2003-01-28 Tue Jari Aalto * dyndns.pl (sub Initialize): 1.40 status message change: 'Update good and successful, IP updated"' => 'Ok, update succeeded.'. 2003-01-25 Sat Jari Aalto * dyndns.pl (Help): 1.40 Added topic LINUX CONTROL SCRIPT 2002-10-31 Jari Aalto * dyndns.pl (HandleCommandLineArgs): Added --proxy options, suggested by Goetz Andreas 2002-10-02 Wed Jari Aalto * dyndns.pl: 1.25 Changed all no-ip.org references to no-ip.com, which is the correct site. Notified by: No-IP Support 2002-09-30 Mon Jari Aalto * dyndns.pl (HandleCommandLineArgs): 1.25 Change --Offline-option to shorte --Offline. (UpdateNoip): 1.25 Support OFFLINE option by setting IP to 0.0.0.0 2002-09-29 Sun Jari Aalto * dyndns.pl -- NEW FEATURE: It is now possible to find out the IP address for ASDL, cable modem and for other similar servioce types, where the IP address is not DIRECT INTERNEL IP Address, but one that is assigned by the ISPs router. Refer to --help for complete descriptions. (TestDriverHttpPing): 1.25 New. (Help): 1.25 Added new section `ADSL and subnet options'. (HandleCommandLineArgs): 1.25 Added new options `--urlping' and `--urlpingre'. (HttpPing): 1.25 New. (Main): 1.25 Call `HttpPing' if user has supplied parameters. (RunUpdate): 1.25 Changed to code to accept more Dynamic DNS providers. (HandleCommandLineArgs): 1.25 Added option --Provider to select from available Dynamic DNS providers. (Help): 1.25 Added help for option --Provider. (GetIpAddressLast): 1.25 Added FILE parameter. (WriteIpAddress): 1.25 Added FILE parameter. (GetIpAddressInfo): 1.25 Added FILE parameter. (HandleCommandLineArgs): 1.25 Added --group option [noip provider] * admin.bashrc: (sfperldyndoc) Added ode to delete temporary files adter POD generation. 2002-04-28 Sun Jari Aalto * dyndns.pl: 1.23 (sub TestDriver) Added German Win32 response. Featue requested by LongJohn (schlupp) in the Feature Tracker (sub GetIpAddressWin32): 1.23 Added German Win32 regexp support. Address => Add?resse? 2002-04-25 Thu Jari Aalto * dyndns.pl (TestDriver): 1.22 reported BSD 4.3 output parsing problem. Added new test case. (sub GetIpAddressWin32): 1.22 Function mistakenly died if REGEXP did not match. Now prints only warning and continues trying more regexps. 2002-04-21 Sun Jari Aalto * dyndns.pl Dr. Weidong Wang asked support for multiple ethernet cards under windows. It should also be possible to select the correct card. (IpAddressGenericParser): 1.20 Added Multiline match if the single line match fails. (GetIpAddressWin32): 1.20 Added support for multiple ethernet cards. (HandleCommandLineArgs): 1.20 Added new options --daemon and --regexp REGEXP. Clarified documentation. (TestDriver): 1.20 Added test for multiple ethernet cards. (GetIpAddressInfo): 1.20 New. (RunUpdate): 1.20 New. (Main): 1.20 Completely rewritten. (Update): 1.20 Rewritten to accept argument hash. Thi was previously the Main() (GetIpAddressIfconfig): 1.21 Added selecting Linux Ip address by User regexp. 2002-01-20 Sun Jari Aalto * admin.bashrc: (function sfperldyndoc): 1.1 New. Generate documention. * dyndns.pl (sub HandleCommandLineArgs): 1.16 Added OPT_SYSTEM. It is now possible to update values in dyndns|statdns|custom. See http://clients.dyndns.org/devel/query.php (sub Initialize): 1.17 Added error code `!active' (sub StatusCodeParse): 1.18 Added handling wxxh, wxxm and wxxs return codes. (sub HandleCommandLineArgs): 1.18 $HOST is now @HOST to allow updating many hosts simultaneously. (LWP::UserAgent): 1.18 Converted $HOST handling to @HOST. (Getopt::Long): 1.18 Accept -h as --help options. (Help): updated Manal page how to use --Host option to update multiple hosts. (Getopt::Long): 1.19 Added $VERSION_VC to --Version output. Now prints 2002.0120.1.19 where the 1.1) is version rcontrol revision number dyndns-2012.0112/INSTALL000066400000000000000000000022121170362450400143510ustar00rootroot00000000000000INSTALL: Perl dyndns - A Perl Dynamic DNS (DDNS) update client -------------------------------------------------------------- Requirements Extra Perl CPAN modules need to be install before program can be used. See README. You can install additional modules from CPAN with command: perl -MCPAN -e shell cpan> install System wide install Run makefile with appropriate parameters. The program is installed without any file extension (*.pl): make DESTDIR= prefix=/usr/local install To test the installation (to see how files are installed): make install-test find -type f tmp/ Manual install 1. Copy bin/*.pl somewhere along $PATH 2. Copy bin/*.1 somewhere along $MANPATH Study examples/*conf and write your own configuration file (optional; not required) Usage The program contains --daemon mode, which makes program to sleep and wake periodically. This can be used e.g. under Windows. If cron(1) is available, it is recommended to use standard crontab(5) entry to periodically run the program. See manual page and section EXAMPLES. End of file dyndns-2012.0112/Makefile000066400000000000000000000123221170362450400147630ustar00rootroot00000000000000#!/usr/bin/make -f # # Copyright information # # Copyright (C) 1999-2012 Jari Aalto # # License # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ifneq (,) This makefile requires GNU Make. endif PACKAGE = dyndns PACKAGE_DOC = $(PACKAGE) DESTDIR = prefix = /usr exec_prefix = $(prefix) man_prefix = $(prefix)/share mandir = $(man_prefix)/man bindir = $(exec_prefix)/bin sharedir = $(prefix)/share BINDIR = $(DESTDIR)$(bindir) DOCDIR = $(DESTDIR)$(sharedir)/doc/$(PACKAGE_DOC) EXAMPLESDIR = $(DOCDIR)/examples LOCALEDIR = $(DESTDIR)$(sharedir)/locale SHAREDIR = $(DESTDIR)$(sharedir)/$(PACKAGE) LIBDIR = $(DESTDIR)$(prefix)/lib/$(PACKAGE) SBINDIR = $(DESTDIR)$(exec_prefix)/sbin ETCDIR = $(DESTDIR)/etc/$(PACKAGE) # 1 = regular, 5 = conf, 6 = games, 8 = daemons MANDIR = $(DESTDIR)$(mandir) MANDIR1 = $(MANDIR)/man1 MANDIR5 = $(MANDIR)/man5 MANDIR6 = $(MANDIR)/man6 MANDIR8 = $(MANDIR)/man8 TAR = tar TAR_OPT_NO = --exclude='.build' \ --exclude='.sinst' \ --exclude='.inst' \ --exclude='tmp' \ --exclude='*.bak' \ --exclude='*[~\#]' \ --exclude='.\#*' \ --exclude='CVS' \ --exclude='.svn' \ --exclude='.git' \ --exclude='.bzr' \ --exclude='*.tar*' \ --exclude='*.tgz' \ --exclude='Makefile' INSTALL = /usr/bin/install INSTALL_BIN = $(INSTALL) -m 755 INSTALL_DIR = $(INSTALL_BIN) -d INSTALL_DATA = $(INSTALL) -m 644 INSTALL_SUID = $(INSTALL) -m 4755 DIST_DIR = ../build-area DATE = `date +"%Y.%m%d"` VERSION = $(DATE) RELEASE = $(PACKAGE)-$(VERSION) PERL = perl BIN = $(PACKAGE) PL_SCRIPT = bin/$(BIN).pl INSTALL_OBJS_BIN = $(PL_SCRIPT) INSTALL_OBJS_DOC = README INSTALL_OBJS_EXAMPLES = examples/*.conf INSTALL_OBJS_MAN = bin/*.1 all: @echo "Nothing to compile." @echo "Try 'make help' or 'make -n DESTDIR= prefix=/usr/local install'" # Rule: help - display Makefile rules help: grep "^# Rule:" Makefile | sort # Rule: clean - remove temporary files clean: # clean -rm -f *[#~] *.\#* \ *.x~~ pod*.tmp rm -rf tmp distclean: clean realclean: clean # Rule: dist-git - [maintainer] release from Git repository dist-git: test rm -f $(DIST_DIR)/$(RELEASE)* git archive --format=tar --prefix=$(RELEASE)/ master | \ gzip --best > $(DIST_DIR)/$(RELEASE).tar.gz chmod 644 $(DIST_DIR)/$(RELEASE).tar.gz tar -tvf $(DIST_DIR)/$(RELEASE).tar.gz | sort -k 5 ls -la $(DIST_DIR)/$(RELEASE).tar.gz # The "gt" is maintainer's program frontend to Git # Rule: dist-snap - [maintainer] release snapshot from Git repository dist-snap: test @echo gt tar -q -z -p $(PACKAGE) -c -D master # Rule: dist - alias for dist-git dist: dist-git # Rule: dist-ls - [maintainer] list of release files dist-ls: @ls -1tr $(DIST_DIR)/$(PACKAGE)* # Rule: ls - alias for dist-ls ls: dist-ls bin/$(PACKAGE).1: $(PL_SCRIPT) # Make doc: manual page $(PERL) $< --help-man > $@ @-rm -f *.x~~ pod*.tmp doc/manual/index.html: $(PL_SCRIPT) # Make doc: HTML $(PERL) $< --help-html > $@ @-rm -f *.x~~ pod*.tmp doc/manual/index.txt: $(PL_SCRIPT) # Make doc: txt $(PERL) $< --help > $@ @-rm -f *.x~~ pod*.tmp doc/conversion/index.html: doc/conversion/index.txt perl -S t2html.pl --Auto-detect --Out --print-url $< # Rule: man - Generate or update manual page man: bin/$(PACKAGE).1 html: doc/manual/index.html txt: doc/manual/index.txt # Rule: doc - Generate or update all documentation doc: man html txt # Rule: perl-test - Check program syntax perl-test: # perl-test - Check syntax $(PERL) -cw $(PL_SCRIPT) podchecker $(PL_SCRIPT) # Rule: test - Run tests test: perl-test install-doc: doc # install-doc - Install documentation $(INSTALL_DIR) $(DOCDIR) [ ! "$(INSTALL_OBJS_DOC)" ] || \ $(INSTALL_DATA) $(INSTALL_OBJS_DOC) $(DOCDIR) $(TAR) -C doc $(TAR_OPT_NO) --create --file=- . | \ $(TAR) -C $(DOCDIR) --extract --file=- install-examples: # install-examples - Install example configuration files $(INSTALL_DIR) $(EXAMPLESDIR) $(INSTALL_DATA) $(INSTALL_OBJS_EXAMPLES) $(EXAMPLESDIR) install-man: man # install-man - Install manual pages $(INSTALL_DIR) $(MANDIR1) $(INSTALL_DATA) $(INSTALL_OBJS_MAN) $(MANDIR1) install-bin: # install-bin - Install programs $(INSTALL_DIR) $(BINDIR) for f in $(INSTALL_OBJS_BIN); \ do \ dest=$$(basename $$f | sed -e 's/\.pl$$//' -e 's/\.py$$//' ); \ $(INSTALL_BIN) $$f $(BINDIR)/$$dest; \ done # Rule: install - Standard install install: install-bin install-man install-doc install-examples # Rule: install-test - for Maintainer only install-test: rm -rf tmp make DESTDIR=`pwd`/tmp prefix=/usr install find tmp | sort .PHONY: clean distclean realclean .PHONY: install install-bin install-man .PHONY: all man doc test install-test perl-test .PHONY: dist dist-git dist-ls ls # End of file dyndns-2012.0112/Makefile.PL.todo000066400000000000000000000034071170362450400162450ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright information # # Copyright (C) 2003-2012 Jari Aalto # # License # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # Visit . # # Description # # run 'perl *.PL' to generate Makefile use ExtUtils::MakeMaker; WriteMakefile ( NAME => 'perl-dyndns', AUTHOR => 'Jari Aalto ', LICENSE => 'GPL v2 or (at your option) later', ABSTRACT => 'A Perl Dynamic DNS (DDNS) update client', PREREQ_PM => { 'HTTP::Request::Common' => 5.8, 'HTTP::Headers' => 5.8, 'LWP::Simple' => 5.8, 'Sys::Syslog' => 0.20 }, # VERSION => '2008.1111', MAN1EXT => 1, # Not "1p" VERSION_FROM => 'bin/dyndns.pl', EXE_FILES => [qw(bin/dyndns.pl)] ); package MY; # Install without the "*.pl" extension # See: perldoc ExtUtils::MakeMaker; perldoc ExtUtils::MM_Unix sub manifypods { local $_ = shift->SUPER::manifypods(@_); s,(MAN1DIR./.+?).pl,$1,gm; $_; } sub installbin { local $_ = shift->SUPER::installbin(@_); s,(SCRIPT./.+?).pl,$1,gm; $_; } sub postamble { return ' include install.mk install-test:: $(MAKE) DESTDIR=tmp install doc-doc: $(MAKE) -C doc doc:: doc-doc clean-pod-cruft: rm -f *.tmp doc/*.tmp clean:: clean-pod-cruft # Maintainer rule www:: $(MAKE) -C doc www '; } # End of file dyndns-2012.0112/README000066400000000000000000000023451170362450400142070ustar00rootroot00000000000000Perl dyndns - A Perl Dynamic DNS (DDNS) update client ----------------------------------------------------- Map dynamic IP address into your.hostname.example.org. A cross-platform solution for DHCP ISP-connected users to obtain permanent DNS, MX, and Web hosting service from a DDNS provider (e.g. dyndns.org). Works anywhere where Perl is installed. Source package directories bin/ The program doc/ Documentation in various formats examples/ Example files for DDNS configurations Important files INSTALL Install instructions doc/license/LICENSE.txt Licensing information ChangeLog Project change records Project details Homepage http://freecode.com/projects/perl-dyndns Reporting bugs See freecode page Source code repository See freecode page Depends Perl (any version) Extenal CPAN libraries (required): [ Debian: libwww-perl ] HTTP::Request::Common HTTP::Headers LWP::UserAgent LWP::Simple Extenal CPAN libraries (optional): Used only if module is available. In Debian this is packaged as libsys-syslog-perl Sys::Syslog External commands needed: ipconfig (Under WIndows) ifconfig (Under POSIX compliant OS) End of file dyndns-2012.0112/bin/000077500000000000000000000000001170362450400140735ustar00rootroot00000000000000dyndns-2012.0112/bin/dyndns.1000066400000000000000000001134341170362450400154620ustar00rootroot00000000000000.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "DYNDNS 1" .TH DYNDNS 1 "2012-01-12" "perl v5.14.2" "Perl Dynamic DNS Update Client" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" dyndns \- Update IP address to dynamic DNS (DDNS) provider .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& dyndns \-\-login LOGIN \-\-password PASSWORD \e \& \-\-host yourhost.dyndns.org .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" A cross platform Perl client for updating dynamic \s-1DNS\s0 \s-1IP\s0 information at supported providers (see \f(CW\*(C`\-\-provider\*(C'\fR). By Default this program expects www.dyndns.org provider. .PP The dynamic \s-1DNS\s0 services allow mapping a dynamic \s-1IP\s0 address to a static hostname. This way the host can be refered by name instead of the changing \s-1IP\s0 address from the \s-1ISP\s0's pool. Some \s-1DDNS\s0 providers offer a single account and a single host namefree of charge. Please check the information from the Providers' pages. .PP Separate files are used for remembering the last \s-1IP\s0 address to prevent updating the same \s-1IP\s0 address again. This is necessary in order to comply guidelines of the providers where multiple updates of the same \s-1IP\s0 address could cause your domain to be blocked. You should not normally need to touch the files where the \s-1IP\s0 addresses are stored. .PP If you know what you are doing and desperately need a forced update, delete the \s-1IP\s0 files and start program with apropriate arguments. Without the information about previous \s-1IP\s0 address, program sends a new update request to the provider. .PP Program has been designed to work under any version of Windows or Linux, possibly Mac \s-1OS\s0 included. It may not work under other Unix/BSD variants. Please see \s-1BUGS\s0 section how to provide details to add support for other operating systems. .PP Visit the page of the provider and create an account. Write down the login name, password and host name you registered. .PP For Windows operating systems, you need to install Perl. There are two Perl incarnatons: Native Windows version (Activestate Perl) and Cygwin version. The \f(CW\*(C`http://www.cygwin.com/\*(C'\fR is recommended as it more closely follows the original Perl environment. .SH "OPTIONS" .IX Header "OPTIONS" .SS "Gneneral options" .IX Subsection "Gneneral options" .IP "\fB\-\-config=FILE [\-\-config=FILE ...]\fR" 4 .IX Item "--config=FILE [--config=FILE ...]" List of configuration files to read. No command line options other than \fB\-\-verbose\fR, \fB\-\-debug\fR or \fB\-\-test\fR should be appended or results are undefined. Each file must contain complete \s-1DDNS\s0 account configuration. .Sp The \s-1FILE\s0 part will go through Perl's \f(CW\*(C`glob()\*(C'\fR function, meaning that the filenames are expanded. Series of configuration files can be run at once e.g. within directory \f(CW\*(C`/etc/dyndns/\*(C'\fR by using a single option. The order of the files processed is alphabetical: .Sp .Vb 1 \& \-\-config=/etc/dyndns/* .Ve .Sp See section \s-1CONFIGURATION\s0 \s-1FILE\s0 for more information how to write the files. .IP "\fB\-\-host=host1 [\-\-host=host2 ...]\fR" 4 .IX Item "--host=host1 [--host=host2 ...]" Use registered \s-1HOST\s0(s). .IP "\fB\-\-group \s-1GROUP\s0\fR" 4 .IX Item "--group GROUP" \&\fBThis option is only for \-\-provider noip\fR .Sp Assign \s-1IP\s0 to \s-1GROUP\s0. Do you have many hosts that all update to the same \&\s-1IP\s0 address? Update a group instead of a many hosts. .IP "\fB\-\-login \s-1LOGIN\s0\fR" 4 .IX Item "--login LOGIN" \&\s-1DDNS\s0 account's \s-1LOGIN\s0 name. .IP "\fB\-\-mxhost MX-HOST-NAME\fR" 4 .IX Item "--mxhost MX-HOST-NAME" \&\fBThis option is only for \-\-provider dyndns\fR .Sp Update account information with \s-1MX\s0 hostname. Specifies a Mail eXchanger for use with the host being modified. Must resolve to an \fBstatic\fR \s-1IP\s0 address, or it will be ignored. If you don't know \s-1DNS\s0, don't touch this option. .Sp The servers you list need to be correctly configured to accept mail for your hostname, or this will do no good. Setting up a server as an \s-1MX\s0 without permission of the administrator may get them angry at you. If someone is contacted about such an infraction, your \s-1MX\s0 record will be removed and possibly further action taken to prevent it from happening again. Any mail sent to a misconfigured server listed as an \s-1MX\s0 may bounce, and may be lost. .IP "\fB\-\-mx\-option\fR" 4 .IX Item "--mx-option" \&\fBThis option is only for \-\-provider dyndns\fR .Sp Turn on \s-1MX\s0 option. Request that the \s-1MX\s0 in the previous parameter be set up as a backup. This means that mail will first attempt to deliver to your host directly, and will be delivered to the \s-1MX\s0 listed as a backup. .Sp Note regarding provider \f(CW\*(C`noip\*(C'\fR: .Sp Update clients cannot change this value. Clients can only submit requests to the php script to update the A record. Changes such as \s-1MX\s0 records must be done through website. .IP "\fB\-\-offline\fR" 4 .IX Item "--offline" If given, set the host to offline mode. .Sp \&\f(CW\*(C`Note:\*(C'\fR [dyndns] This feature is only available to donators. The \&\*(L"!donator\*(R" return message will appear if this is set on a non-donator host. .Sp This is useful if you will be going offline for an extended period of time. If someone else gets your old \s-1IP\s0 your users will not go to your old \s-1IP\s0 address. .IP "\fB\-\-password \s-1PASSWORD\s0\fR" 4 .IX Item "--password PASSWORD" \&\s-1DDNS\s0 account's \s-1PASSWORD\s0. .IP "\fB\-\-system {dyndns|statdns|custom}\fR" 4 .IX Item "--system {dyndns|statdns|custom}" \&\fBThis option is only for \-\-provider dyndns\fR .Sp The system you wish to use for this update. \f(CW\*(C`dyndns\*(C'\fR will update a dynamic host, \f(CW\*(C`custom\*(C'\fR will update a MyDynDNS Custom \s-1DNS\s0 host and \f(CW\*(C`statdns\*(C'\fR will update a static host. The default value is \f(CW\*(C`dyndns\*(C'\fR and you cannot use other options (statdns|custom) unless you donate and gain access to the more advanced features. .Sp See the \s-1DDNS\s0 provider's pages for more information. .IP "\fB\-\-wildcard\fR" 4 .IX Item "--wildcard" Turn on wildcard option. The wildcard aliases \f(CW\*(C`*.yourhost.ourdomain.ext\*(C'\fR to the same address as \f(CW\*(C`yourhost.ourdomain.ext\*(C'\fR .SS "Additional options" .IX Subsection "Additional options" .IP "\fB\-D, \-\-daemon [\s-1WAIT\-MINUTES\s0]\fR" 4 .IX Item "-D, --daemon [WAIT-MINUTES]" Enter daemon mode. The term \*(L"daemon\*(R" refers to a standalone processes which keep serving until killed. In daemon mode program enters into infinite loop where \s-1IP\s0 address changes are checked periodically. For each new ip address check, program waits for WAIT-MINUTES. Messages in this mode are reported using \fIsyslog\fR\|(3); if available. .Sp This option is designed to be used in systems that do not provide Unix-like cron capabilities (e.g under Windows \s-1OS\s0). It is better to use \fIcron\fR\|(8) and define an entry using \fIcrontab\fR\|(5) notation to run the update in periodic intervals. This will use less memory when Perl is not permanently kept in memory like it would with option \fB\-\-daemon\fR. .Sp The update to \s-1DDNS\s0 provider happens only if .Sp .Vb 3 \& 1) IP address changes \& 2) or it has taken 30 days since last update. \& (See DDNS providers\*(Aq account expiration time documentation) .Ve .Sp The minimum sleep time is 5 minutes. Program will not allow faster wake up times(*). The value can be expressed in formats: .Sp .Vb 4 \& 15 Plain number, minutes \& 15m (m)inutes. Same sa above \& 1h (h)ours \& 1d (d)days .Ve .Sp This options is primarily for permanent Internet connection. If you have a dial-up connection, it is better to arrange the \s-1IP\s0 update at the same time as when the connection is started. In Linux this would happen during \f(CWifup(1)\fR. .Sp (*) Perl language is \s-1CPU\s0 intensive so any faster check would put considerable strain on system resources. Normally a value of 30 or 60 minutes will work fine in most cases. Monitor the \s-1ISP\s0's \s-1IP\s0 rotation time to adjust the time in to use sufficiently long wake up times. .IP "\fB\-\-ethernet [\s-1CARD\s0]\fR" 4 .IX Item "--ethernet [CARD]" In Linux system, the automatic \s-1IP\s0 detection uses program \&\f(CWifconfig(1)\fR. If you have multiple network cards, select the correct card with this option. The default device used for query is \f(CW\*(C`eth0\*(C'\fR. .IP "\fB\-\-file \s-1PREFIX\s0\fR" 4 .IX Item "--file PREFIX" Prefix where to save \s-1IP\s0 information. This can be a) a absolute path name to a file b) directory where to save or c) directory + prefix where to save. Make sure that files in this location do not get deleted. If they are deleted and you happen to update \s-1SAME\s0 ip twice within a short period \- according to www.dyndns.org \s-1FAQ\s0 \- your address may be blocked. .Sp On Windows platform all filenames must use forward slashs like \&\f(CW\*(C`C:/somedir/to/\*(C'\fR, not \f(CW\*(C`C:\esomedir\eto\e\*(C'\fR. .Sp The \s-1PREFIX\s0 is only used as a basename for supported \s-1DDNS\s0 accounts (see \&\fB\-\-provider\fR). The saved filename is constructed like this: .Sp .Vb 3 \& PREFIX\-\-\-.log \& | \& See option \-\-system .Ve .Sp A sample filename in Linux could be something like this if \s-1PREFIX\s0 were set to \f(CW\*(C`/var/log/dyndns/\*(C'\fR: .Sp .Vb 1 \& /var/log/dyndns/eth0\-statdns\-my.dyndns.org\-dyndns.log .Ve .IP "\fB\-f, \-\-file\-default\fR" 4 .IX Item "-f, --file-default" Use reasonable default for saved \s-1IP\s0 file \s-1PREFIX\s0 (see \fB\-\-file\fR). Under Windows, \f(CW%WINDIR\fR% is used. Under Linux the PREFIXes searched are .Sp .Vb 3 \& /var/log/dyndns/ (if directory exists) \& /var/log/ (system\*(Aqs standard) \& $HOME/tmp or $HOME If process is not running under root .Ve .Sp This options is by default activated if \fB\-\-file\fR is not in use. .IP "\fB\-\-proxy \s-1HOST\s0\fR" 4 .IX Item "--proxy HOST" Use \s-1HOST\s0 as outgoing \s-1HTTP\s0 proxy. .IP "\fB\-P, \-\-provider \s-1TYPE\s0\fR" 4 .IX Item "-P, --provider TYPE" By default, program connects to \f(CW\*(C`dyndns.org\*(C'\fR to update the dynamic \s-1IP\s0 address. There are many free dynamic \s-1DNS\s0 providers are reported. Supported list of \s-1TYPES\s0 in alphabetical order: .Sp .Vb 3 \& hnorg No domain name limists \& Basic DDNS service is free (as of 2003\-10\-02) \& http://hn.org/ \& \& dyndns No domain name limits. \& Basic DDNS service is free (as of 2003\-10\-02) \& http://www.dyndns.org/ \& See also http://members.dyndns.org/ \& \& noip No domain name limits. \& Basic DDNS service is free (as of 2003\-10\-02) \& http://www.no\-ip.com/ .Ve .Sp \&\s-1NOTE:\s0 as of 2010, the support for sites of hnorg, noip is probably non-working due to changes in the interfaces. Please use only dyndns at this time. .IP "\fB\-\-query\fR" 4 .IX Item "--query" Query current \s-1IP\s0 address and quit. \fBNote:\fR if you use router, you may need \fB\-\-urlping*\fR options, otherwise the \s-1IP\s0 address returned is your subnet's \s-1DHCP\s0 \s-1IP\s0 and not the \s-1ISP\s0's Internet \s-1IP\s0. .Sp Output of the command is at least two string. The second string is \&\f(CW\*(C`last\-ip\-info\-not\-available\*(C'\fR if the saved ip file name is not specified. In order to program to know where to look for saved \s-1IP\s0 files you need to give some \fB\-\-file*\fR or \fB\-\-config\fR option. The second string can also be \&\f(CW\*(C`nochange\*(C'\fR if current \s-1IP\s0 address is same as what was found from saved file. Examples: .Sp .Vb 5 \& 100.197.1.6 last\-ip\-info\-not\-available \& 100.197.1.6 100.197.1.7 \& 100.197.1.6 nochange 18 \& | \& How many days since last saved IP .Ve .Sp \&\fBNote for tool developers:\fR additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right. .IP "\fB\-\-query\-ipchanged ['exitcode']\fR" 4 .IX Item "--query-ipchanged ['exitcode']" Print message if \s-1IP\s0 has changed or not. This option can take an optional string argument \f(CW\*(C`exitcode\*(C'\fR which causes program to indicate changed ip address with standard shell status code (in bash shell that would available at variable \f(CW$?\fR): .Sp .Vb 3 \& $ dyndns \-\-query\-ipchange exitcode \-\-file\-default \e \& \-\-provider dyndns \-\-host xxx.dyndns.org \& $ echo $? \& \& ... the status code of shell ($?) would be: \& \& 0 true value, changed \& 1 false value, error code, i.e. not changed .Ve .Sp Without the \f(CW\*(C`exitcode\*(C'\fR argument, the returned strings are: .Sp .Vb 7 \& Current IP address \& | \& changed 35 111.222.333.444 \& nochange 18 \& | \& Days since last IP update. Based on saved IP file\*(Aqs \& time stamp. .Ve .Sp If the last saved \s-1IP\s0 file's time stamp is too old, then even if the \s-1IP\s0 were not really changed, the situation is reported with word \f(CW\*(C`changed\*(C'\fR. This is due to time limits the \s-1DDNS\s0 providers have. The account would expire unless it is updated in \s-1NN\s0 days. .Sp \&\fBNote for tool developers:\fR additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right. .IP "\fB\-\-query\-ipfile\fR" 4 .IX Item "--query-ipfile" Print the name of the \s-1IP\s0 file and quit. .Sp \&\fBNote:\fR In order for this option to work, you must supply all other options would be normally pass to update the \s-1DDNS\s0 account, because the Ip filename depends on these options. Alternatively provide option \fB\-\-config \&\s-1FILE\s0\fR from where all relevant information if read. .Sp .Vb 4 \& \-\-ethernet [optional, defaults to eth0] \& \-\-provider [optional, defaults to dyndns] \& \-\-system [optional, defaults to dyndns] \& \-\-host required. .Ve .Sp Here is an example which supposed that directory \f(CW\*(C`/var/log/dyndns/\*(C'\fR already exists: .Sp .Vb 3 \& $ dyndns \-\-file\-default \-\-query\-ipfile \e \& \-\-provider dyndns \-\-host xxx.dyndns.org \& /var/log/dyndns/eth0\-dyndns\-dyndns\-xxx\-dyndns.org.log .Ve .IP "\fB\-\-regexp \s-1REGEXP\s0\fR" 4 .IX Item "--regexp REGEXP" In host, which has multiple netword cards, the response can include multiple \s-1IP\s0 addresses. The default is to pick always the first choice, but that may not be what is wanted. The regexp \s-1MUST\s0 not contain capturing parentheses: if you need one, use non-capturing choice (?:). Refer to Perl manual page \f(CW\*(C`perlre\*(C'\fR for more information about non-cpaturing regular expression parentheses. .Sp Here is an example from Windows: .Sp .Vb 1 \& Ethernet adapter {3C317757\-AEE8\-4DA7\-9B68\-C67B4D344103}: \& \& Connection\-specific DNS Suffix . : \& Autoconfiguration IP Address. . . : 169.254.241.150 \& Subnet Mask . . . . . . . . . . . : 255.255.0.0 \& Default Gateway . . . . . . . . . : \& \& Ethernet adapter Local Area Connection 3: \& \& Connection\-specific DNS Suffix . : somewhere.net \& IP Address. . . . . . . . . . . . : 193.10.221.45 \& Subnet Mask . . . . . . . . . . . : 255.255.0.0 \& Default Gateway . . . . . . . . . : 10.10.0.101 .Ve .Sp The 193.10.221.45 is the intended dynamic \s-1IP\s0 address, not the first one. To instruct searching from somewhere else in the listing, supply a regular expressions that can match a portion in the listing after which the \s-1IP\s0 address appears. In the above case, the regexp could be: .Sp .Vb 1 \& \-\-regexp "Connection 3:" .Ve .Sp In Windows, the words that follow \*(L"\s-1IP\s0 Address\*(R" are automatically expected, so you should not add them to the regexp. .Sp In FreeBSD 4.5, you may get following response: .Sp .Vb 7 \& tun0: flags mtu 1492 \& inet6 fe80::250:4ff:feef:7998%tun0 prefixlen 64 scopeid 0x7 \& inet 62.214.33.49 \-\-> 255.255.255.255 netmask 0xffffffff \& inet 62.214.32.12 \-\-> 255.255.255.255 netmask 0xffffffff \& inet 62.214.35.49 \-\-> 255.255.255.255 netmask 0xffffffff \& inet 62.214.33.163 \-\-> 62.214.32.1 netmask 0xff000000 \& Opened by PID 64 .Ve .Sp The correct \s-1IP\s0 address to pick from the listing is the one, which does not contain netmask 0xffffffff. The picked address for above is therefore 62.214.33.163. The regexp that finds that line is: .Sp .Vb 4 \& \-\-regexp ".*0xffffffff.*?inet" \& | | \& | Search minimum match until word "inet" \& search maximum match .Ve .Sp This will match all the way until the the last line with netmask 0xffffffff, after which shortest match \f(CW\*(C`.*?\*(C'\fR to \f(CW\*(C`inet\*(C'\fR is reached to read the number following it. The regexp must make sure that the next word after its match point is the wanted address. .SS "Cable, \s-1DSL\s0 and router options" .IX Subsection "Cable, DSL and router options" If you do not have direct access to world known \f(CW\*(C`real\*(C'\fR \s-1IP\s0 address, but to a subnet \s-1IP\s0 address, then you cannot determine your outside world \s-1IP\s0 address from your machine directly. See picture below: .PP .Vb 7 \& router/subnet Internet \& +\-\-\-\-\-\-\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-\-\-\-\-+ \& Your PC: | | maps address | | \& connect to ISP \-\-> | ROUTER | \-\-\-\-\-\-\-\-\-\-\-\-\-> | | \& | 192.168.... | | 80.1.1.1 | \& local ip says: +\-\-\-\-\-\-\-\-\-\-\-\-\-+ +\-\-\-\-\-\-\-\-\-\-\-+ \& 192.168.xxx.xxx THE REAL IP .Ve .PP \&\s-1ASDL\s0 and cable modem and other connections may not be directly connected to Internet, but to a router to allow subnnetting internal hosts. This makes several computers to access the Internet while the \s-1ISP\s0 has offered only one visible \s-1IP\s0 address to you. The router makes the mapping of the local subnet \&\s-1IP\s0 to the world known \s-1IP\s0 address, provided by the \s-1ISP\s0 when the connection was established. .PP You need some way to find out what is the real \s-1IP\s0 is. The simplest way is to connect to a some web page, which runs a reverse lookup service which can show the connecting \s-1IP\s0 address. .PP Note: the following web web page does not exists. To find a service that is able to display your \s-1IP\s0 address, do a google search. Let's say, that you found a fictional service \&\f(CW\*(C`http://www.example.com/showip\*(C'\fR and somewhere in the web page it reads: .PP .Vb 1 \& Your IP address is: 212.111.11.10 .Ve .PP This is what you need. To automate the lookup from web page, you need to instruct the program to connect to \s-1URL\s0 page and tell how to read the ip from page by using a regular expression. Consult Perl's manual page \f(CW\*(C`perlre\*(C'\fR if you are unfamiliar with the regular expressions. For the above fictional service, the options needed would be: .PP .Vb 8 \& \-\-urlping "http://showip.org/?showit.pl" \& \-\-urlping\-regexp "address is:\es+([\ed.]+)" \& | || \& | |+\- Read all digits and periods \& | | \& | +\- capturing parentheses \& | \& +\- expect any number of whitespaces .Ve .PP \&\s-1NOTE:\s0 The text to match from web page is not text/plain, but text/html, so you must look at the \s-1HTML\s0 page's sources to match the \s-1IP\s0 address correctly without the bold tags etc. .IP "\fB\-\-urlping \s-1URL\s0\fR" 4 .IX Item "--urlping URL" Web page where world known \s-1IP\s0 address can be read. If you find a Web server that is running some program, which can show your \s-1IP\s0 addres, use it. The example below connects to site and calls \s-1CGI\s0 program to make show the connector's \s-1IP\s0 address. Be polite. Making calls like this too often may cause putting blocks to your site. .Sp .Vb 1 \& http://www.dyndns.org/cgi\-bin/check_ip.cgi .Ve .Sp Be sure to use period of 60 minutes or more with \fB\-\-daemon\fR option to not increase the load in the \*(L"ping\*(R" site and cause admin's to shut down the service. .IP "\fB\-\-urlping\-dyndns\fR" 4 .IX Item "--urlping-dyndns" Contact http://www.dyndns.org service to obtain \s-1IP\s0 address information. This is shorthand to more general optiopn \fB\-\-urlping\fR. .IP "\fB\-\-urlping\-linksys [\s-1TYPE\s0]\fR" 4 .IX Item "--urlping-linksys [TYPE]" \&\fBSpecialized router option for Linksys products\fR. .Sp This option connects to Linksys Wireless \s-1LAN\s0 4\-point router, whose page is by default at local network address \-. The world known \s-1IP\s0 address (which is provided by \s-1ISP\s0) is parsed from that page. The product is typically connected to the cable or \s-1DSL\s0 modem. Refer to routing picture presented previously. .Sp If the default login and password has been changed, options \&\fB\-\-urlping\-login\fR and \fB\-\-urlping\-password\fR must be supplied .Sp For \s-1TYPE\s0 information, See . Products codes currently supported include: .Sp .Vb 4 \& \- BEFW11S4, Wireless Access Point Router with 4\-Port Switch. \& Page: http://192.168.1.1/Status.htm \& \- WRT54GL, Wireless WRT54GL Wireless\-G Broadband Router. \& Page: http://192.168.1.1/Status_Router.asp .Ve .IP "\fB\-\-urlping\-login \s-1LOGIN\s0\fR" 4 .IX Item "--urlping-login LOGIN" If \f(CW\*(C`\-\-urlping\*(C'\fR web page requires authentication, supply user name for a secured web page. .IP "\fB\-\-urlping\-password \s-1LOGIN\s0\fR" 4 .IX Item "--urlping-password LOGIN" If \f(CW\*(C`\-\-urlping\*(C'\fR web page requires authentication, supply password for a secured web page. .IP "\fB\-\-urlping\-regexp \s-1REGEXP\s0\fR" 4 .IX Item "--urlping-regexp REGEXP" After connecting to page with \fB\-\-urlping \s-1URL\s0\fR, the web page is examined for \&\s-1REGEXP\s0. The regexp must catch the \s-1IP\s0 to perl match \f(CW$1\fR. Use non-capturing parenthesis to control the match as needed. For example this is incorrect: .Sp .Vb 3 \& \-\-urlping\-regexp "(Address|addr:)\es+([0\-9.]+)" \& | | \& $1 $2 .Ve .Sp The match \s-1MUST\s0 be in \*(L"$1\*(R", so you must use non-capturing perl paentheses for the first one: .Sp .Vb 3 \& \-\-urlping\-regexp "(?:Address|addr:) +([0\-9.]+)" \& | | \& non\-capturing $1 .Ve .Sp If this option is not given, the default value is to find first word that matches: .Sp .Vb 1 \& ([0\-9]+\e.[0\-9]+\e.[0\-9]+\e.[0\-9]+) .Ve .SS "Miscellaneous options" .IX Subsection "Miscellaneous options" .IP "\fB\-\-debug [\s-1LEVEL\s0]\fR" 4 .IX Item "--debug [LEVEL]" Turn on debug with optional positive \s-1LEVEL\s0. Use this if you want to know details how the program initiates connection or if you experience trouble contacting \s-1DDNS\s0 provider. .IP "\fB\-\-help\fR" 4 .IX Item "--help" Print help .IP "\fB\-\-help\-html\fR" 4 .IX Item "--help-html" Print help in \s-1HTML\s0 format. .IP "\fB\-\-help\-man\fR" 4 .IX Item "--help-man" Print help page in Unix manual page format. You want to feed this output to \&\fBnroff \-man\fR in order to read it. .IP "\fB\-\-test [\s-1LEVEL\s0]\fR" 4 .IX Item "--test [LEVEL]" Run in test mode, do not actually update anything. \s-1LEVEL\s0 1 allows sending \s-1HTTP\s0 ping options and getting answers. .IP "\fB\-\-test\-driver\fR" 4 .IX Item "--test-driver" This is for developer only. Run internal integrity tests. .IP "\fB\-\-test\-account\fR" 4 .IX Item "--test-account" This is for developer only. Uses \s-1DYNDNS\s0 test account options. All command line values that set host information or provider are ignored. Refer to client page at http://clients.dyndns.org/devel .IP "\fB\-\-verbose\fR" 4 .IX Item "--verbose" Print informational messages. .IP "\fB\-\-version\fR" 4 .IX Item "--version" Print version and contact information. .SH "EXAMPLES" .IX Header "EXAMPLES" To update \s-1IP\s0 address periodically, use \fIcrontab\fR\|(5) entry. The update will happen only if \s-1IP\s0 has changed since last time: .PP .Vb 1 \& 0 0\-23 * * * perl /dyndns .Ve .PP To check current \s-1IP\s0 address: .PP .Vb 3 \& dyndns \-\-query [\-\-urlping...] \& | \& Select correct option to do the "ping" for IP .Ve .PP Show where the ip file is/would be stored with given connect options. The option \fB\-\-file\-default\fR uses \s-1OS\s0's default directory structure. .PP .Vb 2 \& dyndns \-\-file\-default \-\-query\-ipfile \-\-provider dyndns \e \& \-\-host xxx.dyndns.org .Ve .PP To upate account information to \s-1DDNS\s0 provider: .PP .Vb 1 \& dyndns \-\-provider dyndns \-\-login \-\-password \-\-host your.dyndns.org .Ve .PP If your router can display a web page containing the world known \s-1IP\s0 address, you can instruct to \*(L"ping\*(R" it. Suppose that router is at address 192.168.1.1 and page that displays the world known \s-1IP\s0 is \&\f(CW\*(C`status.html\*(C'\fR, and you have to log in to the router using username \&\f(CW\*(C`foo\*(C'\fR and password \f(CW\*(C`bar\*(C'\fR: .PP .Vb 3 \& dyndns \-\-urlping http://192.168.1.1/Status.html \e \& \-\-urlping\-login foo \e \& \-\-urlping\-pass bar \e .Ve .PP If the default regexp does not find \s-1IP\s0 address from the page, supply your own match with option \fB\-\-urlping\-regexp\fR. In case of doubt, add option \fB\-\-debug 1\fR and examine the responses. In serious doubt, contact the maintainer (see option \fB\-\-version\fR) and send the full debug output. .PP Tip: if you run a local web server, provider \f(CW\*(C`www.dyndns.org\*(C'\fR can direct calls to it. See option \f(CW\*(C`\-\-wildcard\*(C'\fR to enable `*.your.dyndns.org' domain delegation, like if it we accessed using `www.your.dyndns.org'. .SH "CONFIGURATION FILE" .IX Header "CONFIGURATION FILE" Instead of supplying options at command line, they can be stored to a configuration file. For each \s-1DDNS\s0 account and different domains, a separate configuration file must be created. The configuration files are read with option \fB\-\-config\fR. .PP The syntax of the configuration file includes comments that start with (#). Anything after hash-sign is interpreted as comment. Values are set in \s-1KEY\s0 = \&\s-1VALUE\s0 fashion, where spaces are non-significant. Keys are not case sensitive, but values are. .PP Below, lines marked with [default] need only be set if the default value needs to be changed. Lines marked with [noip] or [dyndns] apply to only those providers' \s-1DDNS\s0 accounts. Notice that some keys, like \f(CW\*(C`host\*(C'\fR, can take multple values seprated by colons. On/Off options take values [1/0] respectively. All host name values below are fictional. .PP .Vb 1 \& # /etc/dyndns/dyndns.conf \& \& # Set to "yes" to make this configuration file excluded \& # from updates. \& \& disable = no # [default] \& \& ethernet = eth0 # [default] \& group = mygourp # Provider [noip] only. \& host = host1.dyndns.org, host1.dyndns.org \& \& # If you route mail. See dyndns.org documentation for details \& # how to set up MX records. If you know nothing about DNS/BIND \& # Don\*(Aqt even consider using this option. Misuse or broken \& # DNS at your end will probably terminate your \*(Aqfree\*(Aq dyndns contract. \& \& mxhost = mxhost.dyndns.org \& \& # Details how to get the world known IP address, in case the standard \& # Linux \*(Aqifconfig\*(Aq or Windows \*(Aqipconfig\*(Aq programs cannot be used. This \& # interests mainly Cable, DSL and router owners. NOTE: You may \& # not use all these options. E.g. [urlping\-linksys4] is alternate \& # to [urlping] etc. See documentation. \& \& urlping\-linksys = BEFW11S4 \& urlping\-login = joe \& urlping\-password = mypass \& \& urlping = fictional.showip.org \& urlping\-regexp = (?:Address|addr:)\es+([0\-9.]+) \& \& # Where IPs are stored. Directory name or Directory name with \& # additional file prefix. The directory part must exist. You could \& # say \*(Aqfile = /var/log/dyndns/\*(Aq but that\*(Aqs the default. \& \& file = default # Use OS\*(Aqs default location \& \& # The DDNS account details \& \& login = mylogin \& password = mypass \& provider = dyndns # [default] \& proxy = myproxy.myisp.net # set only if needed for HTTP calls \& \& # Hou need this option only if you have multiple ethernet cards. \& # After which regexp the IP number appers in ifconfig(1) listing? \& \& regexp = .*0xffffffff.*?inet \& \& # What account are you using? Select \*(Aqdyndns|statdns|custom\*(Aq \& \& system = dyndns # Provider [dyndns] only \& \& # Yes, delegate all *.mydomain.dyndns.org calls \& \& wildcard = 1 \& \& # End of cnfiguration file .Ve .PP See the details of all of these options from the corresponding command line option descriptions. E.g. option 'ethernet' in configuration file corresponds to \fB\-\-ethernet\fR command line option. The normal configuration file for average user would only include few lines: .PP .Vb 1 \& # /etc/dyndns/myhost.dyndns.org.conf \& \& host = myhost.dyndns.org \& file = default # Use OS\*(Aqs default location \& login = mylogin \& password = mypassword \& provider = dyndns \& system = dyndns # or \*(Aqstatdns\*(Aq \& wildcard = 1 # Delegate *.mydomain.dyndns.org \& \& # End of cnfiguration file .Ve .PP \&\s-1TODO\s0 (write Debian daemon scripts) \s-1FIXME:\s0 .PP .Vb 1 \& update\-rc.d dyndns start 3 4 5 6 # Debian .Ve .SH "SUPPORT REQUESTS" .IX Header "SUPPORT REQUESTS" For new Operating System, provide all relevant commands, their options, examples and their output which answer to following questions. The items in parentheses are examples from Linux: .PP .Vb 7 \& \- How is the OS detected? Send result of \*(Aqid \-a\*(Aq, or if file/dir \& structure can be used to detect the system. In Lunux the \& existence of /boot/vmlinuz could indicate that "this is a Linux \& OS". \& \- What is the command to get network information (commandlike \*(Aqifconfig\*(Aq) \& \- Where are the system configuration files stored (in directory /etc?) \& \- Where are the log files stored (under /var/log?) .Ve .PP To add support for routers that can be connected through \s-1HTTP\s0 protocol or with some other commands, please provide connection details and full \s-1HTTP\s0 response: .PP .Vb 1 \& wget \-O \-dump.html http://192.168.1.0/your\-network/router/page.html .Ve .SH "TROUBLESHOOTING" .IX Header "TROUBLESHOOTING" 1. Turn on \fB\-\-debug\fR to see exact details how the program runs and what \s-1HTTP\s0 requests are sent and received. .PP 2. Most of the <\-\-query> options can't be used standalone. Please see documentation what additional options you need to supply with them. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" .IP "\fB\s-1TMPDIR\s0\fR" 4 .IX Item "TMPDIR" Directory of temporary files. Defaults to system temporary dir. .SH "FILES" .IX Header "FILES" Daemon startup file .PP .Vb 1 \& /etc/default/dyndns .Ve .PP In Linux the syslog message files are: .PP .Vb 2 \& /etc/syslog.conf daemon.err daemon.warning \& /var/log/daemon.log .Ve .PP There is no default location where program would search for configuration files. Configuration files may be found in directory \&\f(CW\*(C`/etc/dyndns/examples\*(C'\fR. It is recommended that the examples are modified and copied one directorory up in order to use option \&\fB\-\-config /etc/dyndns/*\fR. .PP If program is run with Windows Activestate Perl, the log file is stored to file \f(CW\*(C`C:/syslog.txt\*(C'\fR. .SH "EXIT STATUS" .IX Header "EXIT STATUS" Not defined. .SH "DEPENDENCIES" .IX Header "DEPENDENCIES" Uses standard Perl modules. .PP HTTP::Headers HTTP::Request::Common LWP::UserAgent LWP::Simple Sys::Syslog .SH "STANDARDS" .IX Header "STANDARDS" The \fIdyndns\fR provider's client specification is at https://www.dyndns.com/developers/specs/ .SH "BUGS AND LIMITATIONS" .IX Header "BUGS AND LIMITATIONS" .SS "Cygwin syslog" .IX Subsection "Cygwin syslog" There is no syslog daemon in Cygwin. The Cygwin \s-1POSIX\s0 emulation layer takes care about syslog requests. On \s-1NT\s0 and above systems it logs to the Windows's event manager, on Win9x and \s-1ME\s0 a file is created in the root of drive \f(CW\*(C`C:\*(C'\fR. See message for more details. .PP You can see the entries in W2K Start => Settings => Administrative Tools => Computer Management: [ System Tools / Event Viewer / Application ] .SS "Debugging errors" .IX Subsection "Debugging errors" Please use option \fB\-\-debug 2\fR and save the result. Contact maintainer if you find bugs or need new features. .SS "About providers hnorg and noip" .IX Subsection "About providers hnorg and noip" The program is primarily developed and maintained to support dyndns.org. The other providers haven't been tested since 2003. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIsyslog\fR\|(3), Debian package \fIddclient\fR\|(1) .PP See other client software at http://clients.dyndns.org .SH "AVAILABILITY" .IX Header "AVAILABILITY" http://freecode.com/projects/perl\-dyndns .SH "AUTHOR" .IX Header "AUTHOR" This program is free software; you can redistribute and/or modify program under the terms of \s-1GNU\s0 General Public license either version 2 of the License, or (at your option) any later version. .PP The documentation may be distributed subject to the terms and conditions set forth in \s-1GNU\s0 General Public License v2 or later (\s-1GNU\s0 \&\s-1GPL\s0); or, at your option, distributed under the terms of \s-1GNU\s0 Free Documentation License version 1.2 or later (\s-1GNU\s0 \s-1FDL\s0). dyndns-2012.0112/bin/dyndns.pl000066400000000000000000006167671170362450400157560ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright # # Copyright (C) 1999-2012 Jari Aalto # # License # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Documentation # # To read manual, start this program with option: --help # # Details how to update dyndns.org account # # To create an account [2000-11-04] # http://members.dyndns.org/newacct # # According to the developer page at # For more about approved clients for dyndns.org, refer to: # http://clients.dyndns.org/ # # majordomo@dyndns.org with "subscribe devel" in the body of the message # The signup e-mail will have information about the test account # to be used in client testing to avoid blocks on your own account. # # 2001-06, the specification has changed. The new specification # is listed in http://support.dyndns.org/dyndns/clients/devel/query.shtml # and look like this: # # http://username:password@members.dyndns.org/nic/update?system=dyndns&hostname=yourhost.ourdomain.ext,yourhost2.dyndns.org& myip=ipaddress&wildcard=OFF&mx=mail.exchanger.ext&backmx=NO&offline=NO # # GET /nic/update?system=statdns&hostname=yourhost.ourdomain.ext,yourhost2.dyndns.org &myip=ipaddress&wildcard=OFF&mx=mail.exchanger.ext&backmx=NO&offline=NO HTTP/1.1 # Host: members.dyndns.org # Authorization: Basic username:pass (note: username:pass must be encoded in base64) # User-Agent: myclient/1.0 me@null.net # # ...A test account is available for client testing to avoid having your # own hostnames blocked. Hosts test.* (all available domains) can be # updated under this account, and we unblock them on a fairly regular # basis. The username and password for this account are both "test". # # Test commands (developer only information) # # dyndns --system custom --test-account --urlping-linksys4 -d 4 2>&1 | tee ~/dyndns-custom.log # **************************************************************************** # # Globals # # **************************************************************************** # This is for use of Makefile.PL and ExtUtils::MakeMaker # # The following variable is updated by Emacs setup whenever # this file is saved. our $VERSION = '2012.0112.1838'; # **************************************************************************** # # Standard modules # # **************************************************************************** use strict; use English; use File::Basename; use Getopt::Long; use autouse 'Pod::Text' => qw( pod2text ); use autouse 'Pod::Html' => qw( pod2html ); IMPORT: # This is just a syntactic sugar: actually no-op { # Import following environment variables use Env; use vars qw ( $PATH $TMPDIR $SYSTEMROOT $WINDIR ); } # **************************************************************************** # # Modules from CPAN # # **************************************************************************** my @REQUIRE_FATAL = # Without these the program won't work ( 'HTTP::Request::Common' , 'HTTP::Headers' , 'LWP::UserAgent' , 'LWP::Simple' ); my @REQUIRE_OPTIONAL = ( 'Sys::Syslog' ); # Will be set at runtime my @FEATURE_LIST_MODULES; # **************************************************************************** # # DESCRIPTION # # Set global variables for the program # # INPUT PARAMETERS # # none # # RETURN VALUES # # none # # **************************************************************************** sub Initialize () { use vars qw # declare global variables ( $PROGNAME $LIB $LICENSE $AUTHOR $URL $WIN32 $CYGWIN %STATUS_CODE_DYNDNS_HASH @STATUS_CODE_DYNDNS_TRY_AGAIN %STATUS_CODE_NOIP_HASH @STATUS_CODE_NOIP_TRY_AGAIN %STATUS_CODE_HN_HASH @STATUS_CODE_HN_TRY_AGAIN $WIN32_SYSLOG_DIR $WIN32_SYSLOG_FILE $WIN32_SYSLOG_PATH ); $PROGNAME = basename $PROGRAM_NAME; $LIB = $PROGNAME; $LICENSE = "GPL-2+"; $AUTHOR = "Jari Aalto"; $URL = "http://freecode.com/projects/perl-dyndns"; my $id = "$LIB.Initialize"; $WIN32 = 1 if $OSNAME =~ /win32|cygwin/i; $CYGWIN = 1 if $OSNAME =~ /cygwin/i; if ( not $WIN32 or $CYGWIN ) { # Sometimes the PATH is not set correctly. Make sure it # includes these, always. $PATH .= ":/bin:/usr/bin:/sbin:/usr/sbin"; } # For Activestate Perl without Cygwin. $WIN32_SYSLOG_FILE = "syslog.txt"; $WIN32_SYSLOG_DIR = "C:/"; $WIN32_SYSLOG_PATH = $WIN32_SYSLOG_DIR . $WIN32_SYSLOG_FILE; $OUTPUT_AUTOFLUSH = 1; %STATUS_CODE_HN_HASH = ( 101 => "Ok, update succeeded." , 201 => "Failure, previous update was already 300 seconds ago" , 202 => "Failure, server error" , 203 => "Failure, account locked by admin" , 204 => "Failure, account locked by user" ); @STATUS_CODE_HN_TRY_AGAIN = qw ( 101 ); %STATUS_CODE_NOIP_HASH = ( 0 => "No changes; already set. IP update considered abusive" , 1 => "Ok, update succeeded" , 2 => "Incorrect hostname" , 3 => "Bad authorization (password)" , 4 => "Bad authorization (user)" , 6 => "Acocunt has been banned for violating terms of service" , 7 => "Ip is a private network address" , 8 => "Host or acocunt has been disabled by the provider" , 9 => "Cannot update, because it is a web redirect" , 10 => "Group does not exist" , 11 => "Group update succeeded" , 12 => "No changes; already set. Group update considered abusive" , 99 => "This client software has been disabled/expired. " . "Please upgrade to newest version." ); # Codes that signify "You can try again, you made a mistake" @STATUS_CODE_NOIP_TRY_AGAIN = qw ( 2 3 4 7 9 10 ); # 2002-01-01 See http://clients.dyndns.org/devel/codes.php %STATUS_CODE_DYNDNS_HASH = ( # Pre-Update Errors # # The codes above are only only given once, regardless of how many # hosts are in the update. "badauth" => "Bad authorization (username or password)" , "badsys" => "The system parameter given was not valid." , "badagent" => "The useragent your client sent has been blocked" . " at the access level. Support of this return code is optional." # Update Complete # # The codes below indicate that the update was completed, in some # fashion or another. This includes abusive updates, see the # abuse code for more information. # # Note that "update complete" messages will be followed by the IP # address updated for confirmation purposes. This value will be # space-separated from the update code. , "good" => "Ok, update succeeded." , "nochg" => "No changes, update considered abusive" # Input Error Conditions # # The codes below indicate fatal errors, after which updating should # be stopped pending user confirmation of settings or other # appropriate data. # # notfqdn will be returned once if no hosts are given. , "notfqdn" => "A Fully-Qualified Domain Name was not provided." , "nohost" => "The hostname specified does not exist" , "!donator" => "The offline setting was set, when the user" . " is not a donator, this is only returned once" , "!yours" => "The hostname specified exists, but not under" , "!active" => "The hostname specified is in a Custom DNS domain" . " which has not yet been activated. " . "The hostname specified exists, but not under" , "abuse" => "The hostname specified is blocked for abuse;" . " contact support to be unblocked" # Server Error Conditions # # The conditions represented by the codes below should cause the # client to stop and request that the user inform support what # code was received. These are hard server errors that will have # to be investigated. # # Note: dnserr will be followed by a numeric packet ID which # should be reported to the support department along with the # error. , "numhost" => "Too many or too few hosts found" , "dnserr" => "DNS error encountered" # Wait Conditions # # When one of the below codes is received, wait for the specified # conditions to be met before attempting another update. Note: # "xx" can be any integer. Note: An optional explanation of the # delay may be present after the wait code, separated from the # code by a space. Due to difficulties in implementation, the # wuxxxx return has been removed from the spec. , "wxxh" => "Wait xx hours." , "wxxm" => "Wait xx minutes." , "wxxs" => "Wait xx seconds." # Emergency Conditions # To be used when things have all gone horribly wrong, mostly if # the database or DNS server have died for whatever reason. Also # will be sent if the NIC is closed for any reason, unless a # timeframe is known. , "911" => "Shutdown until notified otherwise via status.shtml" # Same as 911, for British users :) , "999" => "Shutdown until notified otherwise via status.shtml" ); @STATUS_CODE_DYNDNS_TRY_AGAIN = ( "badauth" , "badsys" , "notfqdn" , "nohost" , "!yours" , "!active" , "numhost" , "dnserr" ); } # **************************************************************************** # # DESCRIPTION # # Load Perl modules or notify user # # INPUT PARAMETERS # # None # # RETURN VALUES # # None. Dies if cannot load module. # # **************************************************************************** sub InitializeModules () { my $id = "$LIB.InitializeModules"; for my $module ( @REQUIRE_OPTIONAL ) { eval "use $module"; if ( $EVAL_ERROR ) { warn "$id: [WARN] can't load CPAN module $module: $EVAL_ERROR\n" . "Please install with command:\n" . " perl -MCPAN -e shell\n" . " cpan>install $module\n" ; } push @FEATURE_LIST_MODULES, $module; } for my $module ( @REQUIRE_FATAL ) { eval "use $module"; if ( $EVAL_ERROR ) { warn "$id: [FATAL] can't load CPAN module $module: $EVAL_ERROR\n" . "Please install with command:\n" . " perl -MCPAN -e shell\n" . " cpan>install $module\n" ; exit 1; } } } # ***************************************************************** &help **** # # DESCRIPTION # # Print help and exit. # # INPUT PARAMETERS # # $msg [optional] Reason why function was called.- # # RETURN VALUES # # none # # **************************************************************************** =pod =head1 NAME dyndns - Update IP address to dynamic DNS (DDNS) provider =head1 SYNOPSIS dyndns --login LOGIN --password PASSWORD \ --host yourhost.dyndns.org =head1 DESCRIPTION A cross platform Perl client for updating dynamic DNS IP information at supported providers (see C<--provider>). By Default this program expects www.dyndns.org provider. The dynamic DNS services allow mapping a dynamic IP address to a static hostname. This way the host can be refered by name instead of the changing IP address from the ISP's pool. Some DDNS providers offer a single account and a single host namefree of charge. Please check the information from the Providers' pages. Separate files are used for remembering the last IP address to prevent updating the same IP address again. This is necessary in order to comply guidelines of the providers where multiple updates of the same IP address could cause your domain to be blocked. You should not normally need to touch the files where the IP addresses are stored. If you know what you are doing and desperately need a forced update, delete the IP files and start program with apropriate arguments. Without the information about previous IP address, program sends a new update request to the provider. Program has been designed to work under any version of Windows or Linux, possibly Mac OS included. It may not work under other Unix/BSD variants. Please see BUGS section how to provide details to add support for other operating systems. Visit the page of the provider and create an account. Write down the login name, password and host name you registered. For Windows operating systems, you need to install Perl. There are two Perl incarnatons: Native Windows version (Activestate Perl) and Cygwin version. The C is recommended as it more closely follows the original Perl environment. =head1 OPTIONS =head2 Gneneral options =over 4 =item B<--config=FILE [--config=FILE ...]> List of configuration files to read. No command line options other than B<--verbose>, B<--debug> or B<--test> should be appended or results are undefined. Each file must contain complete DDNS account configuration. The FILE part will go through Perl's C function, meaning that the filenames are expanded. Series of configuration files can be run at once e.g. within directory C by using a single option. The order of the files processed is alphabetical: --config=/etc/dyndns/* See section CONFIGURATION FILE for more information how to write the files. =item B<--host=host1 [--host=host2 ...]> Use registered HOST(s). =item B<--group GROUP> B Assign IP to GROUP. Do you have many hosts that all update to the same IP address? Update a group instead of a many hosts. =item B<--login LOGIN> DDNS account's LOGIN name. =item B<--mxhost MX-HOST-NAME> B Update account information with MX hostname. Specifies a Mail eXchanger for use with the host being modified. Must resolve to an B IP address, or it will be ignored. If you don't know DNS, don't touch this option. The servers you list need to be correctly configured to accept mail for your hostname, or this will do no good. Setting up a server as an MX without permission of the administrator may get them angry at you. If someone is contacted about such an infraction, your MX record will be removed and possibly further action taken to prevent it from happening again. Any mail sent to a misconfigured server listed as an MX may bounce, and may be lost. =item B<--mx-option> B Turn on MX option. Request that the MX in the previous parameter be set up as a backup. This means that mail will first attempt to deliver to your host directly, and will be delivered to the MX listed as a backup. Note regarding provider C: Update clients cannot change this value. Clients can only submit requests to the php script to update the A record. Changes such as MX records must be done through website. =item B<--offline> If given, set the host to offline mode. C [dyndns] This feature is only available to donators. The "!donator" return message will appear if this is set on a non-donator host. This is useful if you will be going offline for an extended period of time. If someone else gets your old IP your users will not go to your old IP address. =item B<--password PASSWORD> DDNS account's PASSWORD. =item B<--system {dyndns|statdns|custom}> B The system you wish to use for this update. C will update a dynamic host, C will update a MyDynDNS Custom DNS host and C will update a static host. The default value is C and you cannot use other options (statdns|custom) unless you donate and gain access to the more advanced features. See the DDNS provider's pages for more information. =item B<--wildcard> Turn on wildcard option. The wildcard aliases C<*.yourhost.ourdomain.ext> to the same address as C =back =head2 Additional options =over 4 =item B<-D, --daemon [WAIT-MINUTES]> Enter daemon mode. The term "daemon" refers to a standalone processes which keep serving until killed. In daemon mode program enters into infinite loop where IP address changes are checked periodically. For each new ip address check, program waits for WAIT-MINUTES. Messages in this mode are reported using syslog(3); if available. This option is designed to be used in systems that do not provide Unix-like cron capabilities (e.g under Windows OS). It is better to use cron(8) and define an entry using crontab(5) notation to run the update in periodic intervals. This will use less memory when Perl is not permanently kept in memory like it would with option B<--daemon>. The update to DDNS provider happens only if 1) IP address changes 2) or it has taken 30 days since last update. (See DDNS providers' account expiration time documentation) The minimum sleep time is 5 minutes. Program will not allow faster wake up times(*). The value can be expressed in formats: 15 Plain number, minutes 15m (m)inutes. Same sa above 1h (h)ours 1d (d)days This options is primarily for permanent Internet connection. If you have a dial-up connection, it is better to arrange the IP update at the same time as when the connection is started. In Linux this would happen during C. (*) Perl language is CPU intensive so any faster check would put considerable strain on system resources. Normally a value of 30 or 60 minutes will work fine in most cases. Monitor the ISP's IP rotation time to adjust the time in to use sufficiently long wake up times. =item B<--ethernet [CARD]> In Linux system, the automatic IP detection uses program C. If you have multiple network cards, select the correct card with this option. The default device used for query is C. =item B<--file PREFIX> Prefix where to save IP information. This can be a) a absolute path name to a file b) directory where to save or c) directory + prefix where to save. Make sure that files in this location do not get deleted. If they are deleted and you happen to update SAME ip twice within a short period - according to www.dyndns.org FAQ - your address may be blocked. On Windows platform all filenames must use forward slashs like C, not C. The PREFIX is only used as a basename for supported DDNS accounts (see B<--provider>). The saved filename is constructed like this: PREFIX---.log | See option --system A sample filename in Linux could be something like this if PREFIX were set to C: /var/log/dyndns/eth0-statdns-my.dyndns.org-dyndns.log =item B<-f, --file-default> Use reasonable default for saved IP file PREFIX (see B<--file>). Under Windows, %WINDIR% is used. Under Linux the PREFIXes searched are /var/log/dyndns/ (if directory exists) /var/log/ (system's standard) $HOME/tmp or $HOME If process is not running under root This options is by default activated if B<--file> is not in use. =item B<--proxy HOST> Use HOST as outgoing HTTP proxy. =item B<-P, --provider TYPE> By default, program connects to C to update the dynamic IP address. There are many free dynamic DNS providers are reported. Supported list of TYPES in alphabetical order: hnorg No domain name limists Basic DDNS service is free (as of 2003-10-02) http://hn.org/ dyndns No domain name limits. Basic DDNS service is free (as of 2003-10-02) http://www.dyndns.org/ See also http://members.dyndns.org/ noip No domain name limits. Basic DDNS service is free (as of 2003-10-02) http://www.no-ip.com/ NOTE: as of 2010, the support for sites of hnorg, noip is probably non-working due to changes in the interfaces. Please use only dyndns at this time. =item B<--query> Query current IP address and quit. B if you use router, you may need B<--urlping*> options, otherwise the IP address returned is your subnet's DHCP IP and not the ISP's Internet IP. Output of the command is at least two string. The second string is C if the saved ip file name is not specified. In order to program to know where to look for saved IP files you need to give some B<--file*> or B<--config> option. The second string can also be C if current IP address is same as what was found from saved file. Examples: 100.197.1.6 last-ip-info-not-available 100.197.1.6 100.197.1.7 100.197.1.6 nochange 18 | How many days since last saved IP B additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right. =item B<--query-ipchanged ['exitcode']> Print message if IP has changed or not. This option can take an optional string argument C which causes program to indicate changed ip address with standard shell status code (in bash shell that would available at variable C<$?>): $ dyndns --query-ipchange exitcode --file-default \ --provider dyndns --host xxx.dyndns.org $ echo $? ... the status code of shell ($?) would be: 0 true value, changed 1 false value, error code, i.e. not changed Without the C argument, the returned strings are: Current IP address | changed 35 111.222.333.444 nochange 18 | Days since last IP update. Based on saved IP file's time stamp. If the last saved IP file's time stamp is too old, then even if the IP were not really changed, the situation is reported with word C. This is due to time limits the DDNS providers have. The account would expire unless it is updated in NN days. B additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right. =item B<--query-ipfile> Print the name of the IP file and quit. B In order for this option to work, you must supply all other options would be normally pass to update the DDNS account, because the Ip filename depends on these options. Alternatively provide option B<--config FILE> from where all relevant information if read. --ethernet [optional, defaults to eth0] --provider [optional, defaults to dyndns] --system [optional, defaults to dyndns] --host required. Here is an example which supposed that directory C already exists: $ dyndns --file-default --query-ipfile \ --provider dyndns --host xxx.dyndns.org /var/log/dyndns/eth0-dyndns-dyndns-xxx-dyndns.org.log =item B<--regexp REGEXP> In host, which has multiple netword cards, the response can include multiple IP addresses. The default is to pick always the first choice, but that may not be what is wanted. The regexp MUST not contain capturing parentheses: if you need one, use non-capturing choice (?:). Refer to Perl manual page C for more information about non-cpaturing regular expression parentheses. Here is an example from Windows: Ethernet adapter {3C317757-AEE8-4DA7-9B68-C67B4D344103}: Connection-specific DNS Suffix . : Autoconfiguration IP Address. . . : 169.254.241.150 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . : Ethernet adapter Local Area Connection 3: Connection-specific DNS Suffix . : somewhere.net IP Address. . . . . . . . . . . . : 193.10.221.45 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . : 10.10.0.101 The 193.10.221.45 is the intended dynamic IP address, not the first one. To instruct searching from somewhere else in the listing, supply a regular expressions that can match a portion in the listing after which the IP address appears. In the above case, the regexp could be: --regexp "Connection 3:" In Windows, the words that follow "IP Address" are automatically expected, so you should not add them to the regexp. In FreeBSD 4.5, you may get following response: tun0: flags mtu 1492 inet6 fe80::250:4ff:feef:7998%tun0 prefixlen 64 scopeid 0x7 inet 62.214.33.49 --> 255.255.255.255 netmask 0xffffffff inet 62.214.32.12 --> 255.255.255.255 netmask 0xffffffff inet 62.214.35.49 --> 255.255.255.255 netmask 0xffffffff inet 62.214.33.163 --> 62.214.32.1 netmask 0xff000000 Opened by PID 64 The correct IP address to pick from the listing is the one, which does not contain netmask 0xffffffff. The picked address for above is therefore 62.214.33.163. The regexp that finds that line is: --regexp ".*0xffffffff.*?inet" | | | Search minimum match until word "inet" search maximum match This will match all the way until the the last line with netmask 0xffffffff, after which shortest match C<.*?> to C is reached to read the number following it. The regexp must make sure that the next word after its match point is the wanted address. =back =head2 Cable, DSL and router options If you do not have direct access to world known C IP address, but to a subnet IP address, then you cannot determine your outside world IP address from your machine directly. See picture below: router/subnet Internet +-------------+ +-----------+ Your PC: | | maps address | | connect to ISP --> | ROUTER | -------------> | | | 192.168.... | | 80.1.1.1 | local ip says: +-------------+ +-----------+ 192.168.xxx.xxx THE REAL IP ASDL and cable modem and other connections may not be directly connected to Internet, but to a router to allow subnnetting internal hosts. This makes several computers to access the Internet while the ISP has offered only one visible IP address to you. The router makes the mapping of the local subnet IP to the world known IP address, provided by the ISP when the connection was established. You need some way to find out what is the real IP is. The simplest way is to connect to a some web page, which runs a reverse lookup service which can show the connecting IP address. Note: the following web web page does not exists. To find a service that is able to display your IP address, do a google search. Let's say, that you found a fictional service C and somewhere in the web page it reads: Your IP address is: 212.111.11.10 This is what you need. To automate the lookup from web page, you need to instruct the program to connect to URL page and tell how to read the ip from page by using a regular expression. Consult Perl's manual page C if you are unfamiliar with the regular expressions. For the above fictional service, the options needed would be: --urlping "http://showip.org/?showit.pl" --urlping-regexp "address is:\s+([\d.]+)" | || | |+- Read all digits and periods | | | +- capturing parentheses | +- expect any number of whitespaces NOTE: The text to match from web page is not text/plain, but text/html, so you must look at the HTML page's sources to match the IP address correctly without the bold tags etc. =over 4 =item B<--urlping URL> Web page where world known IP address can be read. If you find a Web server that is running some program, which can show your IP addres, use it. The example below connects to site and calls CGI program to make show the connector's IP address. Be polite. Making calls like this too often may cause putting blocks to your site. http://www.dyndns.org/cgi-bin/check_ip.cgi Be sure to use period of 60 minutes or more with B<--daemon> option to not increase the load in the "ping" site and cause admin's to shut down the service. =item B<--urlping-dyndns> Contact http://www.dyndns.org service to obtain IP address information. This is shorthand to more general optiopn B<--urlping>. =item B<--urlping-linksys [TYPE]> B. This option connects to Linksys Wireless LAN 4-point router, whose page is by default at local network address -. The world known IP address (which is provided by ISP) is parsed from that page. The product is typically connected to the cable or DSL modem. Refer to routing picture presented previously. If the default login and password has been changed, options B<--urlping-login> and B<--urlping-password> must be supplied For TYPE information, See . Products codes currently supported include: - BEFW11S4, Wireless Access Point Router with 4-Port Switch. Page: http://192.168.1.1/Status.htm - WRT54GL, Wireless WRT54GL Wireless-G Broadband Router. Page: http://192.168.1.1/Status_Router.asp =item B<--urlping-login LOGIN> If C<--urlping> web page requires authentication, supply user name for a secured web page. =item B<--urlping-password LOGIN> If C<--urlping> web page requires authentication, supply password for a secured web page. =item B<--urlping-regexp REGEXP> After connecting to page with B<--urlping URL>, the web page is examined for REGEXP. The regexp must catch the IP to perl match $1. Use non-capturing parenthesis to control the match as needed. For example this is incorrect: --urlping-regexp "(Address|addr:)\s+([0-9.]+)" | | $1 $2 The match MUST be in "$1", so you must use non-capturing perl paentheses for the first one: --urlping-regexp "(?:Address|addr:) +([0-9.]+)" | | non-capturing $1 If this option is not given, the default value is to find first word that matches: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) =back =head2 Miscellaneous options =over 4 =item B<--debug [LEVEL]> Turn on debug with optional positive LEVEL. Use this if you want to know details how the program initiates connection or if you experience trouble contacting DDNS provider. =item B<--help> Print help =item B<--help-html> Print help in HTML format. =item B<--help-man> Print help page in Unix manual page format. You want to feed this output to B in order to read it. =item B<--test [LEVEL]> Run in test mode, do not actually update anything. LEVEL 1 allows sending HTTP ping options and getting answers. =item B<--test-driver> This is for developer only. Run internal integrity tests. =item B<--test-account> This is for developer only. Uses DYNDNS test account options. All command line values that set host information or provider are ignored. Refer to client page at http://clients.dyndns.org/devel =item B<--verbose> Print informational messages. =item B<--version> Print version and contact information. =back =head1 EXAMPLES To update IP address periodically, use crontab(5) entry. The update will happen only if IP has changed since last time: 0 0-23 * * * perl /dyndns To check current IP address: dyndns --query [--urlping...] | Select correct option to do the "ping" for IP Show where the ip file is/would be stored with given connect options. The option B<--file-default> uses OS's default directory structure. dyndns --file-default --query-ipfile --provider dyndns \ --host xxx.dyndns.org To upate account information to DDNS provider: dyndns --provider dyndns --login --password --host your.dyndns.org If your router can display a web page containing the world known IP address, you can instruct to "ping" it. Suppose that router is at address 192.168.1.1 and page that displays the world known IP is C, and you have to log in to the router using username C and password C: dyndns --urlping http://192.168.1.1/Status.html \ --urlping-login foo \ --urlping-pass bar \ If the default regexp does not find IP address from the page, supply your own match with option B<--urlping-regexp>. In case of doubt, add option B<--debug 1> and examine the responses. In serious doubt, contact the maintainer (see option B<--version>) and send the full debug output. Tip: if you run a local web server, provider C can direct calls to it. See option C<--wildcard> to enable `*.your.dyndns.org' domain delegation, like if it we accessed using `www.your.dyndns.org'. =head1 CONFIGURATION FILE Instead of supplying options at command line, they can be stored to a configuration file. For each DDNS account and different domains, a separate configuration file must be created. The configuration files are read with option B<--config>. The syntax of the configuration file includes comments that start with (#). Anything after hash-sign is interpreted as comment. Values are set in KEY = VALUE fashion, where spaces are non-significant. Keys are not case sensitive, but values are. Below, lines marked with [default] need only be set if the default value needs to be changed. Lines marked with [noip] or [dyndns] apply to only those providers' DDNS accounts. Notice that some keys, like C, can take multple values seprated by colons. On/Off options take values [1/0] respectively. All host name values below are fictional. # /etc/dyndns/dyndns.conf # Set to "yes" to make this configuration file excluded # from updates. disable = no # [default] ethernet = eth0 # [default] group = mygourp # Provider [noip] only. host = host1.dyndns.org, host1.dyndns.org # If you route mail. See dyndns.org documentation for details # how to set up MX records. If you know nothing about DNS/BIND # Don't even consider using this option. Misuse or broken # DNS at your end will probably terminate your 'free' dyndns contract. mxhost = mxhost.dyndns.org # Details how to get the world known IP address, in case the standard # Linux 'ifconfig' or Windows 'ipconfig' programs cannot be used. This # interests mainly Cable, DSL and router owners. NOTE: You may # not use all these options. E.g. [urlping-linksys4] is alternate # to [urlping] etc. See documentation. urlping-linksys = BEFW11S4 urlping-login = joe urlping-password = mypass urlping = fictional.showip.org urlping-regexp = (?:Address|addr:)\s+([0-9.]+) # Where IPs are stored. Directory name or Directory name with # additional file prefix. The directory part must exist. You could # say 'file = /var/log/dyndns/' but that's the default. file = default # Use OS's default location # The DDNS account details login = mylogin password = mypass provider = dyndns # [default] proxy = myproxy.myisp.net # set only if needed for HTTP calls # Hou need this option only if you have multiple ethernet cards. # After which regexp the IP number appers in ifconfig(1) listing? regexp = .*0xffffffff.*?inet # What account are you using? Select 'dyndns|statdns|custom' system = dyndns # Provider [dyndns] only # Yes, delegate all *.mydomain.dyndns.org calls wildcard = 1 # End of cnfiguration file See the details of all of these options from the corresponding command line option descriptions. E.g. option 'ethernet' in configuration file corresponds to B<--ethernet> command line option. The normal configuration file for average user would only include few lines: # /etc/dyndns/myhost.dyndns.org.conf host = myhost.dyndns.org file = default # Use OS's default location login = mylogin password = mypassword provider = dyndns system = dyndns # or 'statdns' wildcard = 1 # Delegate *.mydomain.dyndns.org # End of cnfiguration file TODO (write Debian daemon scripts) FIXME: update-rc.d dyndns start 3 4 5 6 # Debian =head1 SUPPORT REQUESTS For new Operating System, provide all relevant commands, their options, examples and their output which answer to following questions. The items in parentheses are examples from Linux: - How is the OS detected? Send result of 'id -a', or if file/dir structure can be used to detect the system. In Lunux the existence of /boot/vmlinuz could indicate that "this is a Linux OS". - What is the command to get network information (commandlike 'ifconfig') - Where are the system configuration files stored (in directory /etc?) - Where are the log files stored (under /var/log?) To add support for routers that can be connected through HTTP protocol or with some other commands, please provide connection details and full HTTP response: wget -O -dump.html http://192.168.1.0/your-network/router/page.html =head1 TROUBLESHOOTING 1. Turn on B<--debug> to see exact details how the program runs and what HTTP requests are sent and received. 2. Most of the <--query> options can't be used standalone. Please see documentation what additional options you need to supply with them. =head1 ENVIRONMENT =over 4 =item B Directory of temporary files. Defaults to system temporary dir. =back =head1 FILES Daemon startup file /etc/default/dyndns In Linux the syslog message files are: /etc/syslog.conf daemon.err daemon.warning /var/log/daemon.log There is no default location where program would search for configuration files. Configuration files may be found in directory C. It is recommended that the examples are modified and copied one directorory up in order to use option B<--config /etc/dyndns/*>. If program is run with Windows Activestate Perl, the log file is stored to file C. =head1 EXIT STATUS Not defined. =head1 DEPENDENCIES Uses standard Perl modules. HTTP::Headers HTTP::Request::Common LWP::UserAgent LWP::Simple Sys::Syslog =head1 STANDARDS The I provider's client specification is at https://www.dyndns.com/developers/specs/ =head1 BUGS AND LIMITATIONS =head2 Cygwin syslog There is no syslog daemon in Cygwin. The Cygwin POSIX emulation layer takes care about syslog requests. On NT and above systems it logs to the Windows's event manager, on Win9x and ME a file is created in the root of drive C. See message for more details. You can see the entries in W2K Start => Settings => Administrative Tools => Computer Management: [ System Tools / Event Viewer / Application ] =head2 Debugging errors Please use option B<--debug 2> and save the result. Contact maintainer if you find bugs or need new features. =head2 About providers hnorg and noip The program is primarily developed and maintained to support dyndns.org. The other providers haven't been tested since 2003. =head1 SEE ALSO syslog(3), Debian package ddclient(1) See other client software at http://clients.dyndns.org =head1 AVAILABILITY http://freecode.com/projects/perl-dyndns =head1 AUTHOR This program is free software; you can redistribute and/or modify program under the terms of GNU General Public license either version 2 of the License, or (at your option) any later version. The documentation may be distributed subject to the terms and conditions set forth in GNU General Public License v2 or later (GNU GPL); or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL). =cut sub Help ( ; $ $ ) { my $id = "$LIB.Help"; my $msg = shift; # optional arg, why are we here... my $type = shift; # optional arg, type if ( $type eq -html ) { pod2html $PROGRAM_NAME; } elsif ( $type eq -man ) { eval { require Pod::Man; 1 } or die "$id: Cannot generate Man: $EVAL_ERROR"; my %options; $options{center} = 'Perl Dynamic DNS Update Client'; my $parser = Pod::Man->new(%options); $parser->parse_from_file ($PROGRAM_NAME); } else { system "pod2text $PROGRAM_NAME"; } if ( defined $msg ) { print $msg; exit 1; } exit 0; } # **************************************************************************** # # DESCRIPTION # # Return version string # # INPUT PARAMETERS # # none # # RETURN VALUES # # string # # **************************************************************************** sub Version () { "$VERSION"; } sub VersionInfo () { Version() . " $AUTHOR $LICENSE $URL" } sub VersionPrint () { print( VersionInfo() . "\n"); exit 0; } # ************************************************************** &args ******* # # DESCRIPTION # # Read and interpret command line arguments ARGV. Sets global variables # # INPUT PARAMETERS # # none # # RETURN VALUES # # none # # **************************************************************************** sub HandleCommandLineArgsMain () { my $id = "$LIB.HandleCommandLineArgsMain"; local $ARG; use vars qw ( $OPT_QUERY_IP_CHANGED $OPT_DAEMON $OPT_IGNORE_CONFIG $OPT_ETHERNET $OPT_FORCE $OPT_GROUP @OPT_HOST $OPT_HOSTMX $OPT_HTTP_PING $OPT_HTTP_PING_DYNDNS $OPT_HTTP_PING_LINKSYS $OPT_HTTP_PING_LOGIN $OPT_HTTP_PING_PASSWORD $OPT_HTTP_PING_REGEXP $OPT_IP_FILE $OPT_LOGIN $OPT_MX $OPT_OFFLINE $OPT_PASS $OPT_PROVIDER $OPT_PROXY $OPT_QUERY $OPT_QUERY_IP_FILE $OPT_QUERY_IP_SAVED $OPT_REGEXP $OPT_SYSTEM $OPT_WILDCARD $debug $verb $test $DAEMON_MIN @OPT_CONFIG_FILE %CONFIG_FILE_MAP_TABLE @CONFIG_COMMAND_LINE_TABLE @REQUIRED_UPDATE_OPTION_LIST ); $DAEMON_MIN = 5; # What comand line options to preserve, if configuration file # does not define the value. @CONFIG_COMMAND_LINE_TABLE = qw ( OPT_DAEMON OPT_ETHERNET OPT_HTTP_PING OPT_HTTP_PING_DYNDNS OPT_HTTP_PING_LINKSYS4 OPT_HTTP_PING_LOGIN OPT_HTTP_PING_PASSWORD OPT_HTTP_PING_REGEXP OPT_PROXY ); # Allowed values in configuration file %CONFIG_FILE_MAP_TABLE = ( daemon => '$OPT_DAEMON' , ethernet => '$OPT_ETHERNET' , group => '$OPT_GROUP' , host => '@OPT_HOST' , mxhost => '$OPT_HOSTMX' , urlping => '$OPT_HTTP_PING' , 'urlping-dyndns' => '$OPT_HTTP_PING_DYNDNS' , 'urlping-linksys' => '$OPT_HTTP_PING_LINKSYS' , 'urlping-login' => '$OPT_HTTP_PING_LOGIN' , 'urlping-password' => '$OPT_HTTP_PING_PASSWORD' , 'urlping-regexp' => '$OPT_HTTP_PING_REGEXP' , file => '$OPT_IP_FILE' , login => '$OPT_LOGIN' , mxoption => '$OPT_MX' # , offline => '$OPT_OFFLINE' , password => '$OPT_PASS' , provider => '$OPT_PROVIDER' , proxy => '$OPT_PROXY' , regexp => '$OPT_REGEXP' , system => '$OPT_SYSTEM' # Provide synonyms , wildcard => '$OPT_WILDCARD' , disable => '$OPT_IGNORE_CONFIG' ); # Minumum required options, which must be set, before anything # ic connected to provider. @REQUIRED_UPDATE_OPTION_LIST = ( '@OPT_HOST' , '$OPT_PASS' , '$OPT_LOGIN' , '$OPT_SYSTEM' , '$OPT_PROVIDER' , '$OPT_IP_FILE' ); $debug = -1; $test = -1; # .................................................... read args ... my ( $help, $helpHTML,$helpMan, $version, $testAccount, $testDriver ); my ( $ipfileDefault, $wildcard, $mx, $offline ); if ( grep /--debug|^-d\b/, @ARGV ) { print "$id: ARGV: @ARGV\n"; } Getopt::Long::config( qw ( no_ignore_case )); GetOptions # Getopt::Long ( "config=s@" => \@OPT_CONFIG_FILE , "debug:i" => \$debug , "D|daemon:i" => \$OPT_DAEMON , "ethernet=s" => \$OPT_ETHERNET , "f|file-default" => \$ipfileDefault , "file=s" => \$OPT_IP_FILE , "force" => \$OPT_FORCE , "group=s" => \$OPT_GROUP , "h|help" => \$help , "help-html" => \$helpHTML , "help-man" => \$helpMan , "host=s@" => \@OPT_HOST , "login=s" => \$OPT_LOGIN , "mxhost=s" => \$OPT_HOSTMX , "mx-option" => \$mx , "offline" => \$offline , "password=s" => \$OPT_PASS , "proxy=s" => \$OPT_PROXY , "P|provider=s" => \$OPT_PROVIDER , "q|query" => \$OPT_QUERY , "query-ipfile" => \$OPT_QUERY_IP_FILE , "query-ipsaved" => \$OPT_QUERY_IP_SAVED , "query-ipchanged:s" => \$OPT_QUERY_IP_CHANGED , "regexp=s" => \$OPT_REGEXP , "system=s" => \$OPT_SYSTEM , "t|test:i" => \$test , "test-driver" => \$testDriver , "test-account" => \$testAccount , "urlping=s" => \$OPT_HTTP_PING , "urlping-regexp=s" => \$OPT_HTTP_PING_REGEXP , "urlping-login=s" => \$OPT_HTTP_PING_LOGIN , "urlping-password=s" => \$OPT_HTTP_PING_PASSWORD , "urlping-dyndns" => \$OPT_HTTP_PING_DYNDNS , "urlping-linksys:s" => \$OPT_HTTP_PING_LINKSYS , "verbose" => \$verb , "V|version" => \$version , "wildcard" => \$wildcard ); $version and VersionPrint(); $help and Help(); $helpHTML and Help undef, -html; $helpMan and Help undef, -man; $testDriver and TestDriver(); $debug = 1 if $debug == 0; $debug = 0 if $debug < 0; $test = 1 if $test == 0; $test = 0 if $test < 0; $verb = 1 if $debug; $verb = 1 if $test; $OPT_QUERY = 1 if defined $OPT_QUERY; $OPT_FORCE = 1 if defined $OPT_FORCE; $OPT_WILDCARD = 'ON' if defined $wildcard; $OPT_MX = 'YES' if defined $mx; $OPT_OFFLINE = 'YES' if defined $offline; unless ( $OPT_IP_FILE or $ipfileDefault ) { $ipfileDefault = 'on'; } if ( $ipfileDefault ) { $OPT_IP_FILE = SystemLogDir(); $debug and print "$id: OPT_IP_FILE = $OPT_IP_FILE\n"; } # Because this is defined as ':s', this string will be "" if # User supplies option without arguments. We must give # '-undef' to signify that this option has not been used at all # on command line. unless ( defined $OPT_QUERY_IP_CHANGED ) { $OPT_QUERY_IP_CHANGED = '-undef' } else { $OPT_QUERY_IP_CHANGED = 'query' unless $OPT_QUERY_IP_CHANGED; unless ( @OPT_CONFIG_FILE or $OPT_IP_FILE ) { die "$id: Need more details, add option --file* or --config. " , "If you use router, then you also need some " , "--urlping* option" ; } } $OPT_QUERY_IP_FILE = 1 if defined $OPT_QUERY_IP_FILE; $OPT_QUERY_IP_SAVED = 1 if defined $OPT_QUERY_IP_SAVED; $OPT_QUERY = 1 if defined $OPT_QUERY; if ( ($OPT_QUERY_IP_FILE || $OPT_QUERY_IP_SAVED) and not defined @OPT_HOST ) { warn "$id: Option --host should be included with queries."; } if ( defined $OPT_DAEMON ) { $debug and print "$id: OPT_DAEMON was set to $OPT_DAEMON\n"; my $min = $DAEMON_MIN; $OPT_DAEMON = TimeValue($min) if $OPT_DAEMON < $min; $debug and print "$id: DAEMON is using $OPT_DAEMON minutes\n"; } if ( defined $testAccount ) { $OPT_IP_FILE = SystemLogDir(); # See https://www.dyndns.org/developers/testaccount.html if ( ! defined $OPT_SYSTEM ) { die "--system option is missing"; } $OPT_LOGIN = "test"; $OPT_PASS = "test"; @OPT_HOST = ("test.dyndns.org"); if ( $OPT_SYSTEM eq "statdns" ) { $OPT_LOGIN = "test"; $OPT_PASS = "test"; @OPT_HOST = ("test-static.dyndns.org"); } elsif ( $OPT_SYSTEM eq "custom" ) { $OPT_LOGIN = "test"; $OPT_PASS = "test"; @OPT_HOST = ("test1.customtest.dyndns.org"); } } } # **************************************************************************** # # DESCRIPTION # # Write to syslog. # # INPUT PARAMETERS # # $cmd Command with options (with initial arguments, like 'ls -l') # @args Additional arguments # # RETURN VALUES # # true if succeeded. # # **************************************************************************** sub RunCommand ($ @) { my $id = "$LIB.RunCommand"; my ($cmd, @args) = @ARG; # We cannot 'syslog' these messages, because if this fails, # syslog isn't callable either. unless ( $cmd ) { warn "$id: COMMAND is empty" unless $OPT_DAEMON; return; } local *PIPE; unless ( open PIPE, "| $cmd" ) { warn "$id: cannot start $cmd" unless $OPT_DAEMON; return; } my $status = 1; if ( @args ) { unless( print PIPE @args ) { warn "$id: cannot write [@args] to PIPE [$cmd]" unless $OPT_DAEMON; $status = 0; } } unless ( close PIPE ) { warn "$id: cannot close PIPE [$cmd]" unless $OPT_DAEMON; } $status; } # **************************************************************************** # # DESCRIPTION # # Write tog to syslog. # # INPUT PARAMETERS # # $msg # # RETURN VALUES # # None. # # **************************************************************************** sub LogSyslog ($) { my $id = "$LIB.LogSyslog"; my ($msg) = @ARG; $debug and print "$id: INPUT '$msg'\n"; # syslog() calls dies unless there is message. return unless $msg; my $date = DateISO(); my $prefix = "$LIB\[$PID]"; my $facility = 'daemon'; my $priority = 'warning'; my $pString = "$facility.$priority"; $priority = 'err' if $msg =~ /ERROR|PANIC/; # Maybe remove these, they are for consele printing, syslog uses # priority levels. # $msg =~ s,\[(WARN|ERROR|PANIC)\]\s*,,; my $syslog = grep /syslog/i, @FEATURE_LIST_MODULES; if ( $CYGWIN ) { # Syslog Perl module does not work under Cygwin my $cmd = "syslog -p$pString -t$prefix"; $debug and print "$id: Cygwin command: $cmd '$msg'\n"; RunCommand $cmd, $msg; } elsif ( $WIN32 ) { # Native Windows perl (Activestate) my $dir = $WIN32_SYSLOG_DIR; my $path = $WIN32_SYSLOG_PATH; $dir =~ s,/$,,; $dir =~ s,\\,/,g; my $err = "Directory does not exist: $dir" unless -d $dir; if ( -d $dir ) { chomp $msg; FileWrite( $path, -append, "$date $prefix $pString $msg\n"); } } elsif ( $syslog ) { my $err; LOOP: { my $s = "Sys::Syslog::"; unless( openlog( "dyndns", "pid", $facility) ) { $err = "${s}openlog error [$ERRNO]"; last LOOP; } unless ( syslog( "$priority", $msg ) ) { $err = "${s}syslog error [$ERRNO]"; last LOOP; } unless ( closelog() ) { # Manual page does not say that error is possible # $err = "${s}closelog error [$ERRNO]"; last LOOP; } } $debug and print "$id: used Perl module. Status [$err]\n"; } else # no syslog { $msg .= "\n" unless m,\n\Z,; print STDERR "$date $prefix $pString $msg"; } } # **************************************************************************** # # DESCRIPTION # # Write tog to syslog if running in DAEMON mode. Otherwise print # standard warn(). # # INPUT PARAMETERS # # $msg # $line [optional] Location of the error in this program. # # RETURN VALUES # # None. # # **************************************************************************** sub Log ($;$) { my ($msg, $line) = @ARG; $msg =~ /\n$/ or $msg .= "\n"; if ( $line ) { $msg .= " $PROGRAM_NAME at line $line\n"; } if ( $OPT_DAEMON ) { LogSyslog $msg; } else { print STDERR $msg; } } # **************************************************************************** # # DESCRIPTION # # Convert tokens 7m, 2h, 3d into minutes. Die if value is not numeric. # # INPUT PARAMETERS # # none # # RETURN VALUES # # none # # **************************************************************************** sub TimeValue ($) { my $id = "$LIB.TimeValue"; local ($ARG) = (@ARG); if ( /^(\d+)([mhd]?)$/ ) { $ARG = $1; my $spec = $2 if defined $2; $debug and print "$id: val [$ARG] spec [$spec]\n"; my $factor = 1; $factor = 60 if $spec =~ /h/i; $factor = 60 *24 if $spec =~ /d/i; $ARG *= $factor; $debug and print "$id: val [$ARG] factor [$factor]\n"; } else { die "$id: Not a recognized time value [$ARG]. Try 2m, 2d, 2h"; } $ARG; } # *************************************************************************** # # DESCRIPTION # # Check that set variables make sense. Programs dies if there are # errors. # # INPUT PARAMETERS # # $file [optional] File name being checked (conf file) # # RETURN VALUES # # None # # **************************************************************************** sub VariableCheckValidity (; $) { my $id = "$LIB.VariableCheckValidity"; my ($file) = @ARG; my $msg = "[at $file]" if $file; $debug and print "$id:\n"; sub OnOff($$$); local *OnOff = sub ($$$) { my ($var, $val, $arrRef) = @ARG; $debug and print "$id.OnOff: $var [$val]\n"; if ( $val =~ /on/i or $val > 0 ) { $val = (@$arrRef)[0]; } else { $val = (@$arrRef)[1]; } VariableEval( $var, $val ); }; # default values $OPT_ETHERNET = "eth0" unless defined $OPT_ETHERNET; $OPT_SYSTEM = "dyndns" unless defined $OPT_SYSTEM; $OPT_PROVIDER = "dyndns" unless defined $OPT_PROVIDER; OnOff '$OPT_WILDCARD', $OPT_WILDCARD, [qw(ON OFF)]; OnOff '$OPT_MX' , $OPT_MX , [qw(YES NO)]; OnOff '$OPT_OFFLINE' , $OPT_OFFLINE , [qw(YES NO)]; if ( not $test and not $OPT_QUERY and not $OPT_QUERY_IP_FILE and not $OPT_QUERY_IP_SAVED and not $OPT_QUERY_IP_CHANGED ) { unless ( $OPT_LOGIN and $OPT_PASS and @OPT_HOST) { die "$id: ${msg}Need minimum options: " . "--login $OPT_LOGIN --pass $OPT_PASS --host @OPT_HOST"; } } if ( defined $OPT_HTTP_PING_PASSWORD and not defined $OPT_HTTP_PING_LOGIN ) { # E.g. www.linksys.com router doesn't care about login name, # just the password. $verb and print "$id: ${msg}--urlping-login not set. Login is [login]"; $OPT_HTTP_PING_LOGIN = "login"; } if ( defined $OPT_HTTP_PING_LOGIN and not defined $OPT_HTTP_PING_PASSWORD ) { die "--urlping-passwrd not set."; } unless ( $OPT_SYSTEM =~ /dyndns|statdns|custom/ ) { die "$id: ${msg}Invalid --system value: [$OPT_SYSTEM]. See --help."; } if ( $OPT_HTTP_PING and ( $OPT_HTTP_PING_LINKSYS or $OPT_HTTP_PING_DYNDNS ) ) { die "$id: ${msg}Choose only one --urlping* option."; } if ( $OPT_HTTP_PING and not $OPT_HTTP_PING_REGEXP ) { # Cable and DSL router say that it is a WAN IP, not the LAN ip. # this is like reading from page: # # LAN: # MAC Address: zzzzz # IP Address: 192.168.1.1 # WAN:x # MAC Address: zzzzz # IP Address: xxx.xxx.xxx.xxx << READ THIS my $ip = '([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'; my $maybe = '(?i)(?:WAN.+?IP\s+Address.+?)'; $OPT_HTTP_PING_REGEXP = $maybe . $ip; $verb and Log "$id: [WARN] ${msg}--urlping-regexp is missing, " . "using default regexp $OPT_HTTP_PING_REGEXP"; } } # *************************************************************************** # # DESCRIPTION # # Check that enough variables hold values in order to start doing # IP update request. # # INPUT PARAMETERS # # $file [optional] File name being checked (conf file) # # RETURN VALUES # # false If there is not enough variables. # # **************************************************************************** sub VariableCheckMinimum (; $) { my $id = "$LIB.VariableCheckMinimum"; my ($file) = @ARG; my $msg = " at $file " if $file; my $stat = 1; $debug and print "$id: $file\n"; { no strict; # Due to "eval" in here. for my $var ( @REQUIRED_UPDATE_OPTION_LIST ) { my $result = ''; my $eval = '$result = ' . $var; eval $eval; $debug and print "$id: EVAL $eval => $result\n"; unless ( $result ) { $verb and Log "$id: [ERROR]${msg}$var is not set\n"; $stat = 0; } } } $debug and print "$id: return [$stat]\n"; $stat; } # **************************************************************************** # # DESCRIPTION # # Set perl variables # # INPUT PARAMETERS # # $variable This is string like '$var' or '@list'. # $value This is string. Value to set to. # # RETURN VALUES # # None. # # **************************************************************************** sub VariableEval ($;$) { my $id = "$LIB.VariableEval"; my($variable, $value) = @ARG; no strict; my ($type, $name) = $variable =~ /^(.)(.*)/; if ( $type eq '@' ) { $debug > 1 and print "$id: \@$name = $value\n"; @{$name} = $value; } else { $debug > 1 and print "$id: \$$name = $value\n"; ${$name} = $value; } } # **************************************************************************** # # DESCRIPTION # # Parse sublevel 1 regexp form input string. # # INPUT PARAMETERS # # $string # $regexp # # RETURN VALUES # # MATCH At grouping expression 1 # # **************************************************************************** sub StringRegexpMatch ($$) { my $id = "StringRegexpMatch"; my($str, $regexp) = @ARG; my $ret = ''; if ( $str =~ /$regexp/ ) { $ret = $1; } $debug and print "$id: return [$ret] regexp [$regexp] \n"; $ret; } # **************************************************************************** # # DESCRIPTION # # Find OS's temporary directory # # INPUT PARAMETERS # # none # # RETURN VALUES # # $dir If one found # # **************************************************************************** sub TempDir () { my $id = "$LIB.TempDir"; my $ret; for my $try ( $TMPDIR, qw(/tmp c:/temp c:/) ) { if ( $try and -d $try ) { $ret = $try; last; } } if ( not $ret or not -d $ret ) { die "$id: [FATAL] Cannot set temporary directory. Set TMPDIR."; } $debug and print "$id: $ret"; $ret; } # **************************************************************************** # # DESCRIPTION # # Try to guess system's log directory. In windows, use %WINDIR% # or %SYSTEMROOT% and in Linux and Unix this usually if /var/log # # INPUT PARAMETERS # # none # # RETURN VALUES # # $dir If one found # # **************************************************************************** sub SystemLogDir () { my $id = "$LIB.SystemLogDir"; my $ret = ''; my $root; if ( not $WIN32 and $EUID == 0 ) { $root = "yes"; } if ( -d '/var/log' and ($WIN32 or $root) ) { # Under Win32/Cygwin this directory may exist, but user # does not have permission to it under *nix. $ret = '/var/log'; # See if thee is subdirectory, created by this package's # install phase (in case user did run it) my $try = "$ret/dyndns"; $ret = $try if -d $try; } elsif ( $WIN32 ) { # Don't try to use these variables in any other system, # even if they were set. That's why if-case for Win32. if ( defined $SYSTEMROOT and -d $SYSTEMROOT ) { $ret = $SYSTEMROOT; } elsif ( defined $WINDIR and -d $WINDIR ) { $ret = $WINDIR; } elsif ( -d "C:/" ) { $ret = "C:/" } else { die "$id: [FATAL] This system does not have WINDIR ?"; } } elsif (not $root) { $ret = "$HOME" if -d "$HOME"; $ret = "$HOME/tmp" if -d "$HOME/tmp"; } else { Log "$id: [WARN] $OSNAME not recognized see --help and section BUGS" } $ret =~ s,[/\\]$,,; # Delete trailing slash $ret =~ s,\\,/,g; # convert to forward slashes. if ( $ret and not -d $ret ) { my $try = TempDir(); Log "$id: [WARN] No such directory [$ret]. Do you have permissions? " . "Using backup directory [$try]" ; $ret = $try; } $debug and print "$id: return [$ret]\n"; unless ( $ret ) { die "$id: [FATAL] Nothing to return."; } $ret; } # **************************************************************************** # # DESCRIPTION # # Process each config file option and map them to global # variables. Global hash %CONFIG_FILE_MAP_TABLE provides mappings # from configuration variable to internal global variables. # # INPUT PARAMETERS # # \%hash Reference to hash, key => value # \%global Global values given on command line. Used of configuration # file does not define these. # $file [optional] Used for error message if HASH is empty. # # RETURN VALUES # # none Globals variables are set (See HandleCommandLineArgs) # # **************************************************************************** sub ConfigFileProcess (%) { my $id = "$LIB.ConfigFileProcess"; my %arg = @ARG; my %hash = %{ $arg{-hash} }; my %global = %{ $arg{-global} }; my $file = $arg{-file}; my %map = %CONFIG_FILE_MAP_TABLE; unless ( %hash ) { Log "$id: [WARN] No configuration settings to process from [$file]"; return; } $debug and print "$id: Clearing variables.\n"; while ( my($dummy, $var) = each %map ) { VariableEval $var; } $debug and print "$id: Setting global values.\n"; if ( %global ) { no strict; while ( my($var, $val) = each %global ) { $debug > 1 and printf "$id: GLOBAL $var = %s\n", $val; ${$var} = $val; } } $debug and print "$id: Evaluating configuration values.\n"; my $ret = 1; while ( my($key, $val) = each %hash ) { $key =~ s/(.*)/\L$1/; # case insensitive keys. unless ( exists $map{$key} ) { Log "$id: [WARN] unrecognized option in file $file\n"; next; } my $variable = $map{$key}; $debug and print "$id: config $key [$variable] = $val\n"; # handle option --file-default if ( $key eq 'file' and $val eq 'default' ) { $val = SystemLogDir(); } VariableEval $variable, $val; } $debug and print "$id: return [$ret]\n"; return $ret; } # **************************************************************************** # # DESCRIPTION # # Parse configuration file content. Comments start with '#'. The syntax # is simple. Variable names are not case sensitive. # # variable = value # # INPUT PARAMETERS # # $content # # RETURN VALUES # # %hash variable => value # # **************************************************************************** sub ConfigFileParse ($) { my $id = "$LIB.ConfigFileRead"; local ($ARG) = @ARG; $debug and print "$id: INPUT START\n${ARG}INPUT STOP\n"; my %hash; while ( m,^\s*([^#\r\n\t\f]+)\s*=\s*([^#\r\n\t\f]+),gmxi ) { my $key = $1; my $val = $2; # Delete trailing spaces $key =~ s/\s+$//; $val =~ s/\s+$//; $debug and print "$id: [$key] => [$val]\n"; $hash{ $key } = $val; } %hash; } # **************************************************************************** # # DESCRIPTION # # Read configuration file and set global variables according to it. # # INPUT PARAMETERS # # $file # # RETURN VALUES # # boolean Return false, if file should not be processed. # # **************************************************************************** sub ConfigFileRead ($) { my $id = "$LIB.ConfigFileRead"; my ($file) = @ARG; # Perl does not know $HOME or tilde(~) filenames without a glob. my %globalHash; # Preserve global values if they are not overriden in configuration # files { no strict; for my $name ( @CONFIG_COMMAND_LINE_TABLE ) { if ( defined ${$name} ) { $globalHash{ $name } = ${$name}; $debug > 1 and printf "$id: GLOBAL $name = %s\n", ${$name}; } } } my $expanded; unless ( -f $file ) { $expanded = glob $file; $file = $expanded; } $debug and print "$id: Reading [$file] which expands to [$expanded]\n"; my $content = join '', FileRead( $file); my %hash = ConfigFileParse $content; my $ret = 1; if ( $hash{disable} =~ /yes|1/i ) { $debug and print "$id: skipped. " , "OPT_IGNORE_CONFIG was found from $file\n"; # Configuration file option 'disable' was set $ret = 0; last; } else { ConfigFileProcess -hash => \%hash , -global => \%globalHash , -file => $file ; } return $ret; } # **************************************************************************** # # DESCRIPTION # # Return file where to save the IP address based on values like # ethernet card, provider and update system type. # # INPUT PARAMETERS # # $prefix This is prepended to the beginning of the filename # It can be a directory or directory + prefix. # $absolute if set, then the PREFIX is considered absolute # if it's not a directory, do not try to add # ethernet strings etc. # $hostRef List of hosts whose IP addresses are in question. # # RETURN VALUES # # $file # # **************************************************************************** sub IPfileNamePath (; $$$) { my $id = "IPfileNamePath"; local $ARG = shift; my $abs = shift; my $hostRef = shift; $debug and print "$id: INPUT arg [$ARG] abs [$abs]\n"; $ARG = '' unless defined $ARG; my $ret = ''; if ( $ARG ) { # Add trailing slash if needed. Because the value # is glued to other variables if ( -d ) { $ARG .= '/' unless m,/$,; # This was a directory, not a absolute path name. Clear flag. $abs = ''; } } if ( $ARG and not $abs ) { # The name will contain the *-HOSTA-HOSTB-HOSTC.log if multiple # hosts are updated in batch. If separately, then there will # be different files: *{-HOSTA,-HOSTB,-HOSTC}.log $debug and print "$id ---> making filename\n"; my $HOST = ''; if ( $hostRef ) { my @host = @$hostRef; $debug and print "$id: \@host = @host\n"; @host and $HOST = join '-', @host; } # Last saved IP address is in this file # For multiple network cards, store each one for separate card. # Updates for 'statdns', are different than for 'dyndns' Log "$id: [ERROR] OPT_ETHERNET is empty" unless $OPT_ETHERNET; Log "$id: [ERROR] OPT_PROVIDER is empty" unless $OPT_PROVIDER; my $ethernet = $OPT_ETHERNET . '-' if $OPT_ETHERNET; my $provider = 'noprovider-'; $provider = $OPT_PROVIDER . '-' if $OPT_PROVIDER; my $system = $OPT_SYSTEM . '-' if $OPT_SYSTEM; my $body = $ethernet . $provider . $system . $HOST ; $body =~ s/-$//; # Delete trailing slash $ARG .= $body . ".log"; } $debug and print "$id: $ARG\n"; $ARG; } # **************************************************************************** # # DESCRIPTION # # Return correctly globbed $OPT_IP_FILE. # That variable can be both a directory and a filename, possibly # Shell metacharacters like tilde(~) need to be expanded. # # GLOBAL VARIABLES # # $OPT_IP_FILE must be set before calling this function # # INPUT PARAMETERS # # None # # RETURN VALUES # # $path # # **************************************************************************** sub IPfileNameGlobbed () { my $id = "$LIB.IPfileNameGlobbed"; my $file = $OPT_IP_FILE; $debug and print "$id: OPT_IP_FILE [$file]\n"; $debug and print "$id: OPT_QUERY_IP_FILE [$OPT_QUERY_IP_FILE] " . "OPT_QUERY_IP_SAVED [$OPT_QUERY_IP_SAVED] " . "OPT_QUERY_IP_CHANGED [$OPT_QUERY_IP_CHANGED]\n"; if ( not $file and not ($OPT_QUERY_IP_FILE or $OPT_QUERY_IP_SAVED or ($OPT_QUERY_IP_CHANGED eq -undef) ) ) { # Nothing to check. We don't need to look at previously saved file # User is probably calling with --query or --query-linksys $debug and print "$id: Nothing to do\n"; return; } unless ( $file ) { warn "$id: variable OPT_IP_FILE has no value. " , "Did you forgot to use option --file-default?" ; } if ( $file ) { unless ( -f $file or -d $file ) { my $try = glob $file; $debug and print "$id: flob [$try]\n"; $file = $try if $try; } } $debug and print "$id: return [$file]\n"; $file; } # **************************************************************************** # # DESCRIPTION # # Check valid IP address. # # INPUT PARAMETERS # # $ip # $intenet [optional] If set, consider Internal 192.* and 10.* # addresses valid too. Normally these are not Internet # addresses, but used only for local subnets. # $subnet If set, consider subnet IPs valid (192.x.x.x etc). # # RETURN VALUES # # true, if ok. # # **************************************************************************** sub IPvalidate ($) { my $id = "IPvalidate"; local $ARG = shift; my $subnet = shift; my $ret = 0; $debug and print "$id: [$ARG] subnet [$subnet]\n"; if ( /^\s*\d+\.\d+\.\d+\.\d+\s*$/ ) { $ret = 1; if ( /^\s*(0|192|10)\./ ) { $ret = 0; $ret = 1 if $subnet; $verb and print "$id: ranges 192.* and 10.* are not valid\n"; } } if ( $debug ) { my $action = "[ERROR] IP is not valid."; $ret and $action = "Success."; print "$id: return [$ret] $action\n"; } $ret; } # **************************************************************************** # # DESCRIPTION # # Return strings (B) that are not found in original list (A) # # INPUT PARAMETERS # # \@ original list (A) # \@ list of search elements (B) # # RETURN VALUES # # @ list of elements that were not found from string # # **************************************************************************** sub StringMatch ( $ $ ) { my $id = "$LIB.StringMatch"; my ($itemRef, $searchRef ) = @ARG; unless ( @$itemRef ) { $debug and print "$id: [ERROR] input list is empty." , "items = [@$itemRef]\n"; return; } my @ret; for my $search ( @$searchRef ) { unless ( grep /^\Q$search$/, @$itemRef ) { $debug and print "$id: not found [$search]\n"; push @ret, $search; } } $debug and print "$id: ret = [@ret] input items = [@$itemRef]\n"; @ret; } # **************************************************************************** # # DESCRIPTION # # Construct correct URL # # INPUT PARAMETERS # # $url URL page # $login [optional] how to log in to a secured page # $pass [optional] how to log in to a secured page # # RETURN VALUES # # $url with possible LOGIN and PASS information # # **************************************************************************** sub HttpUrlMake (%) { my $id = "$LIB.HttpUrlMake"; my %arg = @ARG; local $ARG = $arg{-url}; my $login = $arg{-login}; my $pass = $arg{-pass}; if ( $pass and m,(http://)(.+), ) { my ($method, $rest) = ($1, $2); $ARG = $method . "$login:$pass@" . $rest; } $debug and print "$id: return [$ARG]\n"; $ARG; } # **************************************************************************** # # DESCRIPTION # # Return (YYYY, MM, DD, HH, mm) # # INPUT PARAMETERS # # $time [optional]. If not given, return current date # # RETURN VALUES # # @list # # **************************************************************************** sub Date (; $) { my $id = "$LIB.Date"; my ($time) = @ARG; $time = time unless defined $time; my ($yyyy, $MM, $dd, $hh, $mm) = (localtime $time)[5, 4, 3, 2, 1]; $yyyy += 1900; $MM++; $yyyy, $MM, $dd, $hh, $mm; } # **************************************************************************** # # DESCRIPTION # # Return ISO 8601 Date in format 'YYYY-MM-DD HH:mm' # # INPUT PARAMETERS # # $time [optional]. If not given, return current date # # RETURN VALUES # # @list # # **************************************************************************** sub DateISO (; $) { my $id = "$LIB.Date"; my ($time) = @ARG; my($yyyy, $MM, $dd, $hh, $mm) = Date $time; sprintf "$yyyy-%02d-%02d %02d:%02d", $MM, $dd, $hh, $mm; } # **************************************************************************** # # DESCRIPTION # # Calculate diff between TWO dates in days. This is rought estimation, # Not a correct value. # # INPUT PARAMETERS # # \@date1 See return value of Date() # \@date2 See return value of Date() # # RETURN VALUES # # $days Floating point number # # **************************************************************************** sub DateDiffDays ($$) { my $id = "$LIB.DateDiffDays"; my ($date1ref, $date2ref) = @ARG; my ($yyyy, $MM, $dd, $hh, $mm) = @$date1ref; my ($yyyy2, $MM2, $dd2, $hh2, $mm2) = @$date2ref; my $total = ($yyyy2 - $yyyy) * 365; $total += ($MM2 - $MM) * 30; $total += ( ($dd2 * 24 * 60 + $hh2 * 60 + $mm2) - ($dd * 24 * 60 + $hh * 60 + $mm) ) / (24 * 60); $debug and print "$id: $yyyy, $MM, $dd, $hh, $mm | $yyyy2, $MM2, $dd2, $hh2, $mm2\n"; $debug and print "$id: return $total\n"; $total; } # **************************************************************************** # # DESCRIPTION # # File date in format (YYYY, MM, DD) # # INPUT PARAMETERS # # $file # # RETURN VALUES # # @list # # **************************************************************************** sub FileDate ($) { my $id = "$LIB.FileDate"; my ($file) = @ARG; unless ( -f $file ) { $verb > 2 and Log "$id: [WARN] No such file [$file]"; return; } my $mtime = (stat $file)[9]; my @ret = Date $mtime; $debug and print "$id: return @ret\n"; @ret; } # **************************************************************************** # # DESCRIPTION # # Check if the file has been accessed within N days # # INPUT PARAMETERS # # $file File to check # $days Floating point number # # RETURN VALUES # # ( $status, $diff ) # # $status 0 = File has changed. # N = Not touched in N days # $diff float, how many days old # # **************************************************************************** sub IsFileOlderThanDays ($$) { my $id = "$LIB.IsFileOlderThanDays"; my ($file, $days) = @ARG; $debug and print "$id: file [$file] required days [$days]\n"; unless ( -f $file ) { $verb > 2 and Log "$id: [WARN] No such file [$file]"; return 100; } my @fileDate = FileDate $file; my @date = Date(); my $diffDays = DateDiffDays \@fileDate, \@date; my $ret = 0; $ret = $diffDays if $diffDays > $days; $debug and print "$id: file [$file] days $[days], return [$ret]\n"; ( $ret, $diffDays ); } # **************************************************************************** # # DESCRIPTION # # Check if the file has been accessed within N days # # GLOBAL VALUES # # $OPT_PRROVIDER must be set prior calling. (not yet used) # # INPUT PARAMETERS # # $file File to check # # RETURN VALUES # # See function IsFileOlderThanDays() # # **************************************************************************** sub IsFileOld ($) { my $id = "$LIB.IsFileOld"; my ($file) = @ARG; $debug and print "$id: file [$file]\n"; warn "$id: [ERROR] OPT_PROVIDER is not set." unless $OPT_PROVIDER; my ($status, $days); if ( $file ) { ($status, $days) = IsFileOlderThanDays $file, 30; } else { warn "$id: input parameter 'file' is not set."; } $debug and print "$id: RETURN [$status]\n"; ($status, $days); } # **************************************************************************** # # DESCRIPTION # # Connect to a HTTP page from where IP address can be read # # INPUT PARAMETERS # # $url Call string # $regexp How to read the IP address # $login [optional] how to log in to a secured page # $pass [optional] how to log in to a secured page # # RETURN VALUES # # $ip IP number # # **************************************************************************** sub HttpPing (%) { my $id = "$LIB.HttpPing"; my %arg = @ARG; my $url = $arg{-url}; my $regexp = $arg{-regexp}; my $login = $arg{-login}; my $pass = $arg{-pass}; if ( $debug ) { print "$id: input URL [$url] regexp [$regexp} " , "login [$login] pass [$pass]\n" ; } $url = HttpUrlMake -url => $url , -login => $login , -pass => $pass ; unless ( $url and $regexp ) { die "$id: parameters are empty, URL [$url]. ", " Run in debug mode.\n"; } if ( not $url or $url !~ m,http://,i ) { die "$id: invalid URL [$url]. Please check syntax"; } unless ( $regexp =~ /\(/ ) { die "$id: Invalid regexp [$regexp]. Must include parentheses." } my $req = new HTTP::Request( 'GET', $url ); $req->user_agent( "Perl client $PROGNAME/$VERSION"); # $req->header( "Host", $connect ); if ( $test or $debug ) { print $req->as_string; } my $ret = ''; my $ua = new LWP::UserAgent or die "$id: LWP::UserAgent failed $ERRNO"; if ( $test < 2 ) { my $resp = $ua->request( $req ); my $str = $resp->as_string; $debug and print "$str"; $ret = StringRegexpMatch $str, $regexp; } else { $verb and print "$id: No request sent; running in test mode.\n"; $ret = "0.0.0.0"; } $debug and print "$id: return ip [$ret]\n"; $ret; } # **************************************************************************** # # DESCRIPTION # # Connect to a www.dyndns.org and get outbound IP address. # # INPUT PARAMETERS # # none # # RETURN VALUES # # $ip IP address # # **************************************************************************** sub HttpPingDyndns () { my $id = "$LIB.HttpPingDyndns"; $debug and print "$id:\n"; my $regexp = 'IP\s+Address:\s+([\d.]+)'; HttpPing -url => "http://www.dyndns.org/cgi-bin/check_ip.cgi" , -regexp => $regexp ; } # **************************************************************************** # # DESCRIPTION # # Connect to a Linksys WLAN router, and get outbound IP address. # See http://www.linksys.com/ # # This function is for "Wireless AP Router w/4 port Switch" # Model BEFW11S4 # # INPUT PARAMETERS # # $login Login to connect the router # $pass Password to connect the router # # RETURN VALUES # # $ip IP address # # **************************************************************************** sub HttpPingWlanLinksysBEFW11S4 (; $$) { my $id = "$LIB.HttpPingWlanLinksysBEFW11S4"; my ($login, $pass) = @ARG; $login = "admin" unless $login; $debug and print "$id: INPUT login [$login] pass [$pass]\n"; # It is not a password, if there is are no alphanumeric characters # in it. unless ( $pass =~ /[a-z]/i ) { $pass = "admin"; # Use default } # There are two models of BEFW11S4; v2 and v4. The later version # (Cisco version) changed the page from Status.html to # RouterStatus.htm. The page content is also different. # # [v2] # The Response string looks like: # IP Address:81.197.0.2 # # [v4] # Internet IP Address:69.110.12.53< # The LOGIN name is ignored by Linksys. But it has to be provided # in the HTTP call. LOGIN:PASS@SITE. $debug and print "$id: regexp [regexp] login [$login] pass [$pass]\n"; my ($ip, $regexp); # v4 $regexp = 'IP +Address:.+?\s*([\d.]+)'; $ip = HttpPing -url =>"http://192.168.1.1/RouterStatus.htm" , -regexp => $regexp , -login => $login , -pass => $pass ; unless ($ip) { # v2 # There is actually TWO similar lines, the first one is LAN # and the other is WAN ip address. The ".*" at front forces # to pick the last. $regexp = '.*IP +Address:.+?font[^>]+>+([\d.]+)'; $ip = HttpPing -url =>"http://192.168.1.1/Status.htm" , -regexp => $regexp , -login => $login , -pass => $pass ; } $ip; } # **************************************************************************** # # DESCRIPTION # # Connect to a Linksys Model WRT54GL router, and get outbound IP address. # # INPUT PARAMETERS # # $login Login to connect the router # $pass Password to connect the router # # RETURN VALUES # # $ip IP address # # **************************************************************************** sub HttpPingWlanLinksysWRT54GL (; $$) { my $id = "$LIB.HttpPingWlanLinksysWRT54GL"; my ($login, $pass) = @ARG; # This router has empty login by default. $debug and print "$id: INPUT login [$login] pass [$pass]\n"; # It is not a password, if there is are no alphanumeric characters # in it. unless ( $pass =~ /[a-z]/i ) { $pass = "admin"; # Use default } # The Response string looks like: # :  # 81.197.175.198 my $regexp = '(?mi)Capture.*ipaddr.*[\r\n]+.+?font.+?([\d.]+)'; # The LOGIN name is ignored by Linksys. But it has to be provided # in the HTTP call. LOGIN:PASS@SITE. $debug and print "$id: regexp [regexp] login [$login] pass [$pass]\n"; HttpPing -url =>"http://192.168.1.1/Status_Router.asp" , -regexp => $regexp , -login => $login , -pass => $pass ; } # **************************************************************************** # # DESCRIPTION # # ping network HOST # # INPUT PARAMETERS # # $ HOST # # RETURN VALUES # # 1 If connection is okay. # # **************************************************************************** sub Ping ($) { my $id = "$LIB.Ping"; my ($host) = @ARG; my $ret = 0; eval "use Net::Ping"; if ( $EVAL_ERROR ) { Log "$id: [ERROR] Cannot load Net::Ping.pm, please check \@INC\n"; } else { my $ping = Net::Ping->new(); $ret = 1 if $ping->ping($host); $ping->close(); } $debug and print "$id: return [$ret]n"; $ret; } # **************************************************************************** # # DESCRIPTION # # Return last used ip address. # # http://support.dyndns.org/dyndns/faq.shtml # # A Dynamic DNS hostname only needs to # be updated when your IP address has changed. Any updates more # frequently than this - from the same IP address - will be # considered abusive by the update system and may result in your # hostname becoming blocked. Any script which runs periodically # should check to make sure that the IP has actually changed before # making an update, or the host will become blocked. An exception to # this is for users with mostly static IP addresses; you may update # 24-30 days after your previous update with the same IP address to # "touch" the record and prevent it from expiring. Users will receive # an e-mail notification if a host has been unchanged for 28 days. # # INPUT PARAMETERS # # $file File to read # # RETURN VALUES # # string # # **************************************************************************** sub GetIpAddressLast ($) { my $id = "$LIB.GetIpAddressLast"; my ($file) = @ARG; $debug and print "$id: INPUT file to check [$file]\n"; local ( *FILE, $ARG ); if ( $file =~ /^\s*$/ ) { $verb and Log "$id: [WARN] FILE argument is missing, see --file-default\n"; return; } unless ( -f $file ) { $verb and print "$id: No file [$file]\n"; return; } $debug and print "$id: opening [$file]\n"; open FILE, "< $file" or die "$id: Cannot open [$file] $ERRNO"; my $ip; while ( defined( $ARG = ) ) { if ( /^\s*([\d.]+)\s*$/ ) { $ip = $1; last; } } close FILE; $debug and print "$id: return [$ip]\n"; $ip; } # **************************************************************************** # # DESCRIPTION # # Read file # # INPUT PARAMETERS # # $file File # # RETURN VALUES # # @lines # # **************************************************************************** sub FileRead ( $ ) { my $id = "$LIB.FileRead"; my ($file) = @ARG; local *FILE; my @content; unless( open FILE, "< $file" ) { my $msg = "$id: [ERROR] Cannot open [$file] $ERRNO"; if ( $OPT_DAEMON ) { Log $msg; } else { die $msg; } } else { @content = ; close FILE; } @content; } # **************************************************************************** # # DESCRIPTION # # Write message to file. Call syntax: # # FileWrite $file, undef, "String\n"; Replace file # FileWrite $file, -append, "String\n"; Append mode # # INPUT PARAMETERS # # $file File # $append [optional] Append write mode. # @list Strings to write to file # # RETURN VALUES # # true If wrote. # # **************************************************************************** sub FileWrite ( $ $ @ ) { my $id = "$LIB.FileWrite"; my ($file, $append, @list ) = @ARG; $debug and print "$id: INPUT file [$file] append [$append] list [@list]\n"; local ( *FILE, $ARG ); my $status = -wrote; my $mode = ">"; $mode = ">>" if $append; unless ( open FILE, "$mode $file" ) { Log "$id: [ERROR] Cannot write [$file] $ERRNO"; return 0; } unless ( $test ) { unless ( print FILE @list ) { Log "$id: [ERROR] Cannot write '@list' to file $file\n"; $status = ''; } close FILE; $debug and print "$id: Wrote to [$file] content [@list]\n"; } else { $debug and print "$id: test would write [$file] content [@list]\n"; } $status; } # **************************************************************************** # # DESCRIPTION # # Glob (that is, expand) all files in passed LIST. Errors # are displayed for files which do not exist. Directories # in result of glob are discarded # # INPUT PARAMETERS # # @list List of filenames to glob. # For example '~/tmp/*' # # RETURN VALUES # # @list absolute paths to files # # **************************************************************************** sub FileGlob (@) { my $id = "$LIB.FileGlob"; my (@list) = @ARG; $debug and print "$id: INPUT [@list]\n"; my @ret; for my $file ( @list ) { my @glob = glob $file; $debug and print "$id: glob $file => [@glob]\n"; for my $glob ( @glob ) { if ( -d $glob ) { $debug and print "$id: directory [$glob]\n"; } elsif ( not -r $glob ) { $debug and print "$id: not readable [$glob]\n"; } else { push @ret, $glob if $glob; } } } $debug and print "$id: return [@ret]\n"; # I think sort() is not strictly necessary, because glob() # already return the files in alphabetical order. # Be safe: we use this in case Perl some day changes glob(). sort @ret; } # **************************************************************************** # # DESCRIPTION # # See if it is possible to Write to the DIRECTORY or to the FILE. The # FILE is not used, but a FILE.tmp file is tested and then deleted. # # INPUT PARAMETERS # # $file This can be either DIRECTORY of FILE. If DIRECTORY, # then try to write using temporary name. # # RETURN VALUES # # true If writable. # # **************************************************************************** sub FileWriteCheck ( $ ) { my $id = "$LIB.FileWriteCheck"; my ($file) = @ARG; local *FILE; my $status = ''; $debug and print "$id: file [$file]\n"; return unless $file; local *Write = sub ($) { my ($path) = @ARG; my $stamp = join '', Date(); my $postfix = "dyndns-writetest" . $stamp . ".tmp"; $path .= $postfix; my $status = FileWrite $path, undef, "write check"; if ( $status ) { $debug and print "$id: Removing $path\n"; unless ( unlink $path ) { Log "$id: [WARN] Cannot remove $path $ERRNO"; } } $status; }; if ( -d $file ) { $file =~ s,/$,,; $file .= '/'; } $status = Write($file); if ( $debug ) { my $action = "Check failed."; $status and $action = "Good, check passed."; print "$id: return [$status] $action\n"; } $status; } # **************************************************************************** # # DESCRIPTION # # Check if directory or file can be written to. Consequent calls # return cached status and do not actually test the disk any more. # It is expected that permissions on disk do not change. # # INPUT PARAMETERS # # $file Directory or file. # # RETURN VALUES # # true If writable # # **************************************************************************** { my %cacheStatic; sub FileWriteCheckIP ($) { my $id = "$LIB.FileWriteCheckIP"; my ($file) = @ARG; $debug and print "$id: file [$file]\n"; unless ( $file ) { die "$id: Don't know where to save IP. " , "Use --debug to pinpoint the problem if you supplied " , "option --config or --file or --file-default" ; } $debug and print "$id: \@OPT_HOST = @OPT_HOST\n"; $file = IPfileNamePath $file, -absolute, \@OPT_HOST; my $stat; if ( exists $cacheStatic{file} ) { $stat = $cacheStatic{file}; } else { $stat = FileWriteCheck $file; } die "$id: Cannot use [$file].\n" unless $stat; $stat; }} # **************************************************************************** # # DESCRIPTION # # Parse Ip address from INPUT by searching REGEXP line. # IP address must be the first numeric expression. # # INPUT PARAMETERS # # $ regexp. Submatch 1 must contain the IP address portion. # @ List of lines to search. Typically command's output. # # RETURN VALUES # # $ ip address # # **************************************************************************** sub IpAddressGenericParser ( $ @ ) { my $id = "$LIB.IpAddressGenericParser"; my ($regexp, @lines ) = @ARG; local $ARG; my $ip = ''; $debug and print "$id: Response => \n@lines\n"; for ( @lines ) { if ( /$regexp/ ) { if ( not defined $1 ) # User gave non-fucntional regexp { if ( /(\d[\d.]+)/ ) # try generic IP matcher { $ip = $1; } } else { $ip = $1; } $debug and print "$id: Matched [$ARG]\n"; last; } } unless ( $ip ) { $debug and print "$id: Hm, single line did not match. Try multiline match.\n"; # Try full line regexp $ARG = join '', @lines; if ( /$regexp/ ) { $ip = $1; $debug and print "$id: MULTILINE MATCH FOUND => [$ip] $MATCH\n"; } } unless( $ip ) { $verb and Log "$id: [WARN] Can't read IP '$regexp' lines => [@lines]"; } $debug and print "$id: return IP [$ip]\n"; $ip; } # **************************************************************************** # # DESCRIPTION # # Print error message and PATH content if command response is empty. # # INPUT PARAMETERS # # $ Original function name which generated error # $ command # @ command response # # RETURN VALUES # # 1 if LIST is empty # # **************************************************************************** sub CmdError ( $ $ @ ) { my $id = "$LIB.CmdError"; my ($func, $cmd, @list ) = @ARG; my $ret = 0; unless ( @list ) { my @try = qw( /usr/sbin /usr/local/sbin ); my @paths = split $WIN32 ? ";" : ":" , $PATH; my @missing = StringMatch \@paths, \@try ; my $out; $out = "$id: $func [PANIC] command [$cmd] did not return response.\n" . "\tYou may need to add some directory to your PATH." . "Your PATH is now:\n" ; my $i = 0; for my $path ( @paths ) { $i++; $out .= "\t$i $path\n"; } if ( @missing ) { $out .= "\t=> Try adding path"; if ( @missing == 1 ) { $out .= " @missing"; } else { $out .= "s [@missing]\n"; } } Log $out; $ret = 1; } $debug and print "$id: return [$ret]\n"; $ret; } # **************************************************************************** # # DESCRIPTION # # Get current IP by running COMMAND and searching for line # matching REGEXP. The IP address must be the first numeric # expression in the found REGEXP line. # # INPUT PARAMETERS # # $ Command which return IP address # @ Regular expressions to find line containing IP address. # # RETURN VALUES # # $ ip address # # **************************************************************************** sub GetIpAddressGenericParser ( $ @ ) { my $id = "$LIB.GetIpAddressGenericParser"; my ($cmd, @regexp ) = @ARG; my $list = join '', qx($cmd); $debug and print "$id: [$cmd] [$list]\n"; my $stat = CmdError $id, $cmd, $list; $stat and die "$id: $cmd ERROR" ; my $ip; for my $regexp ( @regexp ) { $debug and print "$id: Trying with regexp '$regexp'\n"; $ip = IpAddressGenericParser $regexp, $list; last if $ip; } $ip; } # **************************************************************************** # # DESCRIPTION # # Get current IP by running Win32 IPconfig.exe # # INPUT PARAMETERS # # $ [optional] command to run # # RETURN VALUES # # $ ip address # # **************************************************************************** sub GetIpAddressWin32 (; $) { my $id = "$LIB.GetIpAddressWin32"; my ($cmd) = @ARG; $cmd = "ipconfig" unless $cmd; # The output could look like this: # # PPP adapter tpo128: # # Connection-specific DNS Suffix . : # IP Address. . . . . . . . . . . . : 212.246.177.6 # Subnet Mask . . . . . . . . . . . : 255.255.255.255 # # Notice: The German Win32 reads: # # PPP-Adapter "T-DSL": # Verbindungsspezifisches DNS-Suffix: # IP-Adresse. . . . . . . . . . . . : 80.136.27.233 # Subnetzmaske. . . . . . . . . . . : 255.255.255.255 my $modifier = '(?sm)'; my $base = '(?:inet|IP)(?:.|\s)Add?res[^\r\n:]+:[ \t]*(\d+\.[\d.]+)'; my @regexpList; push @regexpList, $modifier . 'PPP.*' . $base; push @regexpList, $modifier . $base; my $ip; if ( $OPT_REGEXP ) { # If user supplied search criteria, this must be tried first my $try = $modifier . $OPT_REGEXP . ".*" . $base; $ip = GetIpAddressGenericParser $cmd, $try; if ( not $ip and $verb ) { print "$id: [ERROR] User supplied regexp [$OPT_REGEXP] failed. " , "Use --debug to see what went wrong."; } } unless ( $ip ) { $ip = GetIpAddressGenericParser $cmd, @regexpList; } $verb and print "$id: $cmd => $ip\n"; $ip; } # **************************************************************************** # # DESCRIPTION # # Get current IP address information from ethernet CARD. # Global variable OPT_ETHERNET can be set via command line option. # # INPUT PARAMETERS # # none # # RETURN VALUES # # string # # **************************************************************************** sub GetIpAddressIfconfig () { my $id = "$LIB.GetIpAddressIfconfig"; my $cmd = "ifconfig $OPT_ETHERNET"; # $ /sbin/ifconfig eth0 # eth0 Link encap:Ethernet HWaddr 00:10:5A:64:8D:32 # inet addr:12.246.164.15 Bcast:255.255.255.255 Mask:255.255.255.0 # UP BROADCAST RUNNING MTU:1500 Metric:1 # RX packets:38180 errors:0 dropped:0 overruns:0 frame:0 # TX packets:12211 errors:0 dropped:0 overruns:0 carrier:1 # collisions:46 txqueuelen:100 # Interrupt:11 Base address:0xec00 # my $re = '(?sm)inet[ \t]+addr:[ \t]*(\d[\d.]+)'; my $modifier = '(?sm)'; my $inet = 'inet[ \t]+'; my $base = '[ \t]*(\d[\d.]+)'; my @regexpList; push @regexpList, $modifier . $inet . "addr:" . $base; push @regexpList, $modifier . $inet . '[^\r\n:]+:' . $base; push @regexpList, $modifier . $inet . $base; $debug and print "$id: CMD [$cmd]\n"; my $ip; if ( $OPT_REGEXP ) { # If user supplied search criteria, this must be tried first my $try = $modifier . $OPT_REGEXP . $base; $ip = GetIpAddressGenericParser $cmd, $try; if ( not $ip and $verb ) { print "$id: [ERROR] User supplied regexp [$OPT_REGEXP] failed. " , "Use --debug to see what went wrong."; } } unless ( $ip ) { $ip = GetIpAddressGenericParser $cmd, @regexpList; } $verb and print "$id: $cmd => $ip\n"; $ip; } # **************************************************************************** # # DESCRIPTION # # Get current IP address information. Dies if cannot detect ip address. # # INPUT PARAMETERS # # none # # RETURN VALUES # # string # # **************************************************************************** sub GetIpAddress () { my $id = "$LIB.GetIpAddress"; my $ret; if ( $OPT_HTTP_PING ) { $debug and print "$id: OPT_HTTP_PING\n"; $ret = HttpPing -url => $OPT_HTTP_PING , -regexp => $OPT_HTTP_PING_REGEXP , -login => $OPT_HTTP_PING_LOGIN , -pass => $OPT_HTTP_PING_PASSWORD ; } elsif ( $OPT_HTTP_PING_DYNDNS ) { $debug and print "$id: OPT_HTTP_PING_DYNDNS\n"; $ret = HttpPingDyndns(); } elsif ( $OPT_HTTP_PING_LINKSYS ) { $debug and print "$id: OPT_HTTP_PING_LINKSYS $OPT_HTTP_PING_LINKSYS\n"; local $ARG = $OPT_HTTP_PING_LINKSYS; if ( /BEFW11S4/i ) { $ret = HttpPingWlanLinksysBEFW11S4 $OPT_HTTP_PING_LOGIN, $OPT_HTTP_PING_PASSWORD; } if ( /WRT54GL/i ) { $ret = HttpPingWlanLinksysWRT54GL $OPT_HTTP_PING_LOGIN, $OPT_HTTP_PING_PASSWORD; } else { warn "$id: Unknown product code: $ARG. Please contact maintainer."; } } elsif ( $WIN32 ) { $debug and print "$id: WIN32\n"; $ret = GetIpAddressWin32(); } elsif ( -x "/sbin/ifconfig" or -x "/usr/sbin/ifconfig") { $debug and print "$id: ifconfig\n"; $ret = GetIpAddressIfconfig(); } else { die "$id: Don't know how to get your IP address in this OS [$OSNAME]." , "Please contain maintainer and let him " , "know your system name + command + result where to get ip " , "information." ; } unless ( $ret ) { my $msg = "$id: [EXIT] Can't read IP address. Please turn on --debug."; Log $msg; die $msg; } $ret; } # **************************************************************************** # # DESCRIPTION # # Return NEW ip address if it has been changed. # # INPUT PARAMETERS # # $file File to read IP address info # $query if true, do not complain about previous IP # # RETURN VALUES # # (IP, "nochange") "nochange" added if the IP adderess has not changed. # (IP, IP) First argument is the new IP address. # The second argument may be missing if there is no # record of old address. # # **************************************************************************** sub GetIpAddressInfo (%) { my $id = "$LIB.GetIpAddressInfo"; my %arg = @ARG; my $file = $arg{-file}; my $query = $arg{-query}; $debug and print "$id: INPUT file [$file] query [$query]\n"; my $ip = GetIpAddress(); my $lastIP = GetIpAddressLast( $file ) || "last-ip-info-not-available"; my @ret = ("nochange"); $debug and print "$id: IP now [$ip] IP last [$lastIP]\n"; if ( defined $ip ) { if ( defined $lastIP ) { if ( $ip eq $lastIP ) { @ret = ($ip, "nochange"); } else { @ret = ($ip, $lastIP); } } else { @ret = ($ip); } } else { $verb and print "$id: Could not get IP address. ", , "Please run --debug\n"; } $debug and print "$id: return [@ret]\n"; @ret; } # **************************************************************************** # # DESCRIPTION # # See if there is anything to inform about status code # # INPUT PARAMETERS # # $code Error code # $description Error descriptions string # $type -dyndns, -noip, -hnorg # # RETURN VALUES # # true If IP update can be tried again. # # **************************************************************************** sub StatusCodeHandle ($ $ $) { my $id = "$LIB.StatusCodeHandle"; my ($code, $desc, $type) = @ARG; my $status = 0; $debug and print "$id: INPUT [$code] [$desc] type [$type]\n"; if ( $type =~ /noip/ ) { my @list = @STATUS_CODE_NOIP_TRY_AGAIN; $debug and print "$id: BOUNCE LIST noip [@list]\n"; # If number is found in "ok" list, then return the status code $status = $code if grep /^$code$/, @list; } elsif ( $type =~ /dyndns/ ) { # This is list of regexps, not numbers my @list = @STATUS_CODE_DYNDNS_TRY_AGAIN; $debug and print "$id: BOUNCE LIST dyndns [@list]\n"; $status = $code if grep /$code/, @list; } elsif ( $type =~ /hnorg/ ) { # This is list of regexps, not numbers my @list = @STATUS_CODE_HN_TRY_AGAIN; $debug and print "$id: BOUNCE LIST hnorg [@list]\n"; $status = $code if grep /$code/, @list; } else { Log "$id: [ERROR] Can't handle unknown provider [$type]."; } if ( $debug ) { my $action = "Success."; $status and $action = "User is allowed to retry based on [$code]."; print "$id: RETURN [$status] $action\n"; } $status; } # **************************************************************************** # # DESCRIPTION # # Parse status code # # INPUT PARAMETERS # # $response HTTP response string # # RETURN VALUES # # $code, $string status code and description string # # **************************************************************************** sub StatusCodeParseDynDns ( $ ) { my $id = "$LIB.StatusCodeParseDynDns"; local ($ARG) = @ARG; # The response look like: # # dyndns.pl.main: Updating IP 212.246.177.25 # HTTP/1.1 200 OK # Connection: close # Date: Sun, 10 Jun 2001 22:11:25 GMT # Pragma: no-cache # Server: Apache/1.3.20 (Unix) mod_perl/1.25 # Content-Type: text/plain # Client-Date: Sun, 10 Jun 2001 22:16:54 GMT # Client-Peer: 66.37.218.209:80 # # nohost 212.246.177.25 # Get last string from the @lines my $code = (reverse split /\n/)[0]; if ( $code =~ /([a-zA-Z]+)/ ) # find first word { $code = $1; } my $desc = "[WARN] there is no return code description " . "defined for [$code]" ; my %hash = %STATUS_CODE_DYNDNS_HASH; if ( exists $hash{$code} ) { $desc = $hash{$code}; } elsif ( $code =~ /w(\d\d)([hms])/i ) { my $min = $1; my $type = $2; if ( exists $hash{"wxx$type"} ) { $desc = $hash{"wxx$type"}; $desc =~ s/ xx /$min/; } } elsif ( $code =~ /good/i ) { $desc = "Update successful."; } $code, $desc; } # **************************************************************************** # # DESCRIPTION # # Parse status code # # INPUT PARAMETERS # # $response HTTP response string # # RETURN VALUES # # $code, $string status code and description string # # **************************************************************************** sub StatusCodeParseNoip ( $ ) { my $id = "$LIB.StatusCodeParseNoip"; local ($ARG) = @ARG; # The response look like: # # HTTP/1.1 200 OK # Connection: close # Date: Sun, 29 Sep 2002 17:39:32 GMT # Server: Apache/1.3.26 (Unix) PHP/4.2.2 mod_ssl/2.8.10 OpenSSL/0.9.6g # Content-Type: text/html # Client-Date: Sun, 29 Sep 2002 17:41:40 GMT # Client-Response-Num: 1 # Client-Transfer-Encoding: chunked # X-Powered-By: PHP/4.2.2 # # status=2 # Get last string from the @lines my $code = (reverse split /\n/)[0]; if ( $code =~ /status=(\d+)/ ) # find first word { $code = $1; } my $desc = "[WARN] there is no ret code description defined for [$code]"; my %hash = %STATUS_CODE_NOIP_HASH; if ( exists $hash{$code} ) { $desc = $hash{$code}; } $code, $desc; } # **************************************************************************** # # DESCRIPTION # # Parse status code # # INPUT PARAMETERS # # $response HTTP response string # # RETURN VALUES # # $code, $string status code and description string # # **************************************************************************** sub StatusCodeParseHNorg( $ ) { my $id = "$LIB.StatusCodeParseNoip"; local ($ARG) = @ARG; my %hash = %STATUS_CODE_HN_HASH; my $code = ''; if ( /status \s+ code:.*?(\d+)/mix ) { $code = $1; } # Default value my $desc = "[WARN] there is no ret code description defined for [$code]"; if ( exists $hash{$code} ) { $desc = $hash{$code}; } $debug and print "$id: code [$code] desc [$desc]\n"; $code, $desc; } # **************************************************************************** # # DESCRIPTION # # Test drivers for the program. Exist when done. These programs are # never run in production release. If you want to run them, uncommand # the Main() call at the end of this file and replace it with call to # any of these functions # # INPUT PARAMETERS # # none # # RETURN VALUES # # none # # **************************************************************************** sub TestDriverConfigFile () { my $id = "TestDriverConfigFile"; $debug = 1; my $content = < "http://ankka.com/?ip" , -regexp => '([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' ; } sub TestDriverHNorg () { $debug = 1; Initialize(); # Need status codes my $str =<<'EOF'; HTTP/1.1 200 OK Connection: close Date: Sat, 29 May 2004 12:03:35 GMT Server: Apache/1.3.28 (Unix) PHP/4.3.4 mod_perl/1.28 Content-Type: text/html Client-Date: Sat, 29 May 2004 12:05:59 GMT Client-Peer: 216.151.80.10:80 Client-Response-Num: 1 Client-Transfer-Encoding: chunked Title: HN.ORG HN.ORG Status Code: 101
Notice: This is not a real response - it's only to stop the automated programs from DoS-ing HN.ORG. The real update mechanism is no longer on the hostname www.hn.org - it's now on the hostname dup.hn.org. EOF StatusCodeParseHNorg $str; $str =<<'EOF'; HTTP/1.1 401 (Unauthorized) Authorization Required Connection: close Date: Fri, 13 Aug 2004 06:06:40 GMT Server: Apache/1.3.28 (Unix) PHP/4.3.4 mod_perl/1.28 WWW-Authenticate: Basic realm="Vanity Host Users" Content-Type: text/html; charset=iso-8859-1 Client-Date: Fri, 13 Aug 2004 06:09:01 GMT Client-Peer: 216.151.80.11:80 Client-Response-Num: 1 Client-Transfer-Encoding: chunked Title: 401 Authorization Required 401 Authorization Required

Authorization Required

This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.

EOF StatusCodeParseHNorg $str; $str =<<'EOF'; HTTP/1.1 200 OK Connection: close Date: Fri, 13 Aug 2004 06:06:25 GMT Server: Apache/1.3.27 (Unix) PHP/4.3.2 Content-Type: text/html Client-Date: Fri, 13 Aug 2004 06:09:02 GMT Client-Peer: 63.215.241.204:80 Client-Response-Num: 1 Client-Transfer-Encoding: chunked X-Powered-By: PHP/4.3.2 status=4 Bad authorization (user) EOF StatusCodeParseHNorg $str; } sub TestDriverLinksysBEFW11S4 () { my $id = "TestDriverLinksysBEFW11S4"; # The page from Linksys router looks like this. my $str =<<'EOF'; HTTP/1.1 200 OK Connection: close Pragma: no-cache Content-Type: text/html Expires: Thu, 13 Dec 1969 10:29:00 GMT Client-Date: Sat, 22 Feb 2003 19:23:34 GMT Client-Response-Num: 1

 SetupPasswordStatusDHCPLogSecurityHelp Advanced 
STATUS
This screen displays the router's current status and settings. This information is read-only.
Host Name:     
Firmware Version:     1.44.2, Dec 20 2002

Login:  

   Disable

LAN:  

   (MAC Address: 00-06-25-A4-EE-D0)
 
   IP Address:192.168.1.1
   Subnet Mask:255.255.255.0
   DHCP server:Enabled

WAN:  

   (MAC Address: 00-06-25-A4-EE-D1)
 
   IP Address:81.197.0.2
   Subnet Mask:255.255.248.0
   Default Gateway:81.197.0.1
   DNS:212.63.10.250
193.229.0.40
193.229.0.49
   DHCP Remaining Time: 0:38:41
  
 
 

EOF $debug = 1; my $re = '.*IP +Address:.+?font[^>]+>+([\d.]+)'; # default test print "$id: REGEXP 1 [$re]\n"; StringRegexpMatch $str, $re; my $ip = '([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'; $re = "(?i)(?:WAN.+?IP +Address.+?)$ip"; print "$id: REGEXP 2 [$re]\n"; StringRegexpMatch $str, $re; } sub TestDriverLinksysBEFW11S4v4 () { # The newer "Cisco model"; my $id = "TestDriverLinksysBEFW11S4b4"; # The page from Linksys router looks like this. my $str =<<'EOF'; HTTP/1.1 200 OK Connection: close Pragma: no-cache Content-Type: text/html Expires: Thu, 13 Dec 1969 10:29:00 GMT Client-Date: Sat, 22 Feb 2003 19:23:34 GMT Client-Response-Num: 1 Setup
Firmware Version: 1.50.10  

Status

Wireless-B Broadband Router BEFW11S4
 
SetupWirelessSecurityApplications & GamingAdministrationStatus
Router

 

Local Network  

Router Information

        
   Firmware Version:1.50.10, Jan 16 2004  
   MAC Address:00-0F-66-23-C2-56  

Internet

   

Configuration Type

  Login Type:PPPOE  
  Login Status:Connected  
   Internet IP Address:69.110.12.53  
   DNS 1:63.203.35.55  
   DNS 2:206.13.28.12  
   DNS 3:0.0.0.0  
    
  
 
    
      
    
    
    
 Router Status

This screen provides the Router's current status information in a read-only format.

Login Type
This field shows the Internet login status. When you choose PPPoE, RAS, PPTP, or HBS as the login method, you can click the Connect button to log in. If you click the Disconnect button, the Router will not dial up again until you click the Connect button.

If your connection is DHCP or Static IP, the Status screen will show you the Internet IP Address, Subnet mask,

More...

 
     
    
EOF $debug = 1; my $re = 'IP +Address:.+?\s*([\d.]+)'; # default test print "$id: REGEXP 1 [$re]\n"; StringRegexpMatch $str, $re; } sub TestDriverLinksysWRT54GL () { my $id = "TestDriverLinksysWRT54GL"; # The page from Linksys router looks like this. my $str =<<'EOF'; HTTP/1.0 200 Ok Cache-Control: no-cache Cache-Control: no-cache Connection: close Date: Wed, 30 Aug 2006 13:11:30 GMT Pragma: no-cache Pragma: no-cache Server: httpd Content-Type: text/html Expires: 0 Expires: 0 Client-Date: Wed, 30 Aug 2006 10:10:50 GMT Client-Peer: 192.168.1.1:80 Client-Response-Num: 1 Link: ; rel="stylesheet"; type="text/css" Title: Router Status Router Status
: v4.30.7   

   WRT54GL
 


&
    

    

    

 

|

|

 

               
      v4.30.7, Jun. 20, 2006    
         
      00:18:39:C0:4F:1A    
      WRT54GL     
           
         

     

       
      81.197.175.198    
    255.255.192.0  
    81.197.128.1  
      1:  193.229.0.40    
      2:  193.229.0.42    
      3:     
      1492    
   
   
           
       
 










 
       
        
EOF $debug = 1; my $re = '(?mi)Capture.*ipaddr.*[\r\n]+.+?font.+?([\d.]+)'; # default test print "$id: REGEXP 1 [$re]\n"; StringRegexpMatch $str, $re; } { my $staticCounter = 0; sub TestDriver () { my $id = "$LIB.TestDriver"; sub Banner(@); local *Banner = sub (@) { $staticCounter++; print "-" x 70, " TEST CASE: ", $staticCounter, @ARG, "\n"; }; print "$id: BEGIN\n\tAny messages you will now see are not important.\n"; $debug = 10; $verb = $debug; LOCAL_TEST: { local $PATH = "/usr/local/bin:/bin"; local $WIN32 = 0; my @paths = split $WIN32 ? ";" : ":" , $PATH; my @missing = StringMatch \@paths, [ "/usr/bin" ]; CmdError $id, $id ; } my (@response, $ip); # Copy from GetIpAddressIfconfig() my $modifier = '(?sm)'; my $inet = 'inet[ \t]+'; my $base = '[ \t]*(\d[\d.]+)'; my $linuxDefaultRegexp = $modifier . $inet . "addr:" . $base; my $regexp; @response = split /\r?\n/, ' eth0 Link encap:Ethernet Endereo de HW 00:15:c5:1b:e1:de inet end.: 189.29.36.92 Bcast:189.29.39.255 Masc:255.255.248.0'; $regexp = $modifier . $inet . '[^\r\n:]+:' . $base; Banner(); $ip = IpAddressGenericParser $regexp, @response; @response = split /\r?\n/, ' eth0 Link encap:Ethernet HWaddr 00:10:5A:64:8D:32 inet addr:12.246.164.15 Bcast:255.255.255.255 Mask:255.255.255.0 UP BROADCAST RUNNING MTU:1500 Metric:1 RX packets:38180 errors:0 dropped:0 overruns:0 frame:0 TX packets:12211 errors:0 dropped:0 overruns:0 carrier:1 collisions:46 txqueuelen:100 Interrupt:11 Base address:0xec00'; Banner(); $ip = IpAddressGenericParser $linuxDefaultRegexp, @response; @response = split /\r?\n/, ' tun0: flags mtu 1492 inet6 fe80::250:4ff:feef:7998%tun0 prefixlen 64 scopeid 0x7 inet 62.214.32.46 --> 62.214.32.1 netmask 0xff000000 Opened by PID 65'; { my $modifier = '(?sm)'; my $inet = 'inet[ \t]+'; my $base = '[ \t]*(\d[\d.]+)'; my @regexpList; push @regexpList, $modifier . $inet . "addr:" . $base; push @regexpList, $modifier . $inet . $base; Banner(); for my $regexp ( @regexpList ) { $ip = IpAddressGenericParser $regexp, join '', @response; last if $ip; } } @response = split /\r?\n/, ' tun0: flags mtu 1492 inet6 fe80::250:4ff:feef:7998%tun0 prefixlen 64 scopeid 0x7 inet 62.214.33.49 --> 255.255.255.255 netmask 0xffffffff inet 62.214.32.12 --> 255.255.255.255 netmask 0xffffffff inet 62.214.35.49 --> 255.255.255.255 netmask 0xffffffff inet 62.214.33.163 --> 62.214.32.1 netmask 0xff000000 Opened by PID 64'; { my $OPT_REGEXP = ".*0xffffffff.*?inet"; my $modifier = '(?sm)'; my $inet = 'inet[ \t]+'; my $base = '[ \t]*(\d[\d.]+)'; my $try = $modifier . $OPT_REGEXP . $base; Banner(); $ip = IpAddressGenericParser $try, @response; } @response = split /\r?\n/, ' Connection-specific DNS Suffix . : IP Address. . . . . . . . . . . . : 212.246.177.28 Subnet Mask . . . . . . . . . . . : 255.255.255.255 Default Gateway . . . . . . . . . : 212.246.177.28'; Banner(); $ip = IpAddressGenericParser 'IP\s+Address.*[ \t](\d[\d.]+)', @response; # German Windows response @response = split /\r?\n/, ' Windows 2000-IP-Konfiguration Ethernetadapter "Realtek": Verbindungsspezifisches DNS-Suffix: IP-Adresse. . . . . . . . . . . . : 192.168.0.1 Subnetzmaske. . . . . . . . . . . : 255.255.255.0 Standardgateway . . . . . . . . . : PPP-Adapter "T-DSL": Verbindungsspezifisches DNS-Suffix: IP-Adresse. . . . . . . . . . . . : 80.136.27.233 Subnetzmaske. . . . . . . . . . . : 255.255.255.255 Standardgateway . . . . . . . . . : 80.136.27.233'; Banner(); $ip = IpAddressGenericParser '(?sm)PPP.*IP-Adresse[^\r\n:]+:[ \t]*(\d[\d.]+)' , @response; @response = split /\r?\n/, ' Windows 2000 IP Configuration Ethernet adapter {3C317757-AEE8-4DA7-9B68-C67B4D344103}: Connection-specific DNS Suffix . : Autoconfiguration IP Address. . . : 169.254.241.150 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . : Ethernet adapter Local Area Connection 3: Connection-specific DNS Suffix . : internalgroove.net IP Address. . . . . . . . . . . . : 10.10.221.45 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . : 10.10.0.101'; Banner " Windows 2000 (A)"; $ip = IpAddressGenericParser 'IP\s+Address.*[ \t](\d[\d.]+)', @response; { my $OPT_REGEXP = 'Local Area Connection'; my $modifier = '(?sm)'; my $base = 'IP\s+Address[^\r\n:]+:[ \t]*(\d[\d.]+)'; my $re = $modifier . $OPT_REGEXP . ".*" . $base; Banner " Windows 2000 (B)"; $ip = IpAddressGenericParser $re, @response; } @response = split /\r?\n/, ' eth0 Link encap:Ethernet Hardware Adresse 00:30:18:ad:c3:d8 inet Adresse:192.168.2.100 Bcast:192.168.2.255 Maske:255.255.255.0 inet6-Adresse: fe80::230:18ff:fead:c3d8/64 Gültigkeitsbereich:Verbindung UP BROADCAST RUNNING MULTICAST MTU:1500 Metrik:1 RX packets:5304043 errors:0 dropped:0 overruns:0 frame:0 TX packets:4033822 errors:0 dropped:0 overruns:0 carrier:0 Kollisionen:0 Sendewarteschlangenlänge:1000 RX bytes:1239418613 (1.1 GiB) TX bytes:1932841726 (1.8 GiB) Interrupt:25 Basisadresse:0x4000 lo Link encap:Lokale Schleife inet Adresse:127.0.0.1 Maske:255.0.0.0 inet6-Adresse: ::1/128 Gültigkeitsbereich:Maschine UP LOOPBACK RUNNING MTU:16436 Metrik:1 RX packets:1838254 errors:0 dropped:0 overruns:0 frame:0 TX packets:1838254 errors:0 dropped:0 overruns:0 carrier:0 Kollisionen:0 Sendewarteschlangenlänge:0 RX bytes:2155983999 (2.0 GiB) TX bytes:2155983999 (2.0 GiB)'; Banner " German"; $ip = IpAddressGenericParser 'inet\s+Add?res.*?[ \t:](\d[\d.]+)', @response; print "$id: END\n"; }} sub TestDriverSyslogWin32cygwin() { Initialize(); my $id = "$LIB.TestDriverSyslogWin32cygwin"; $debug = 1; print "$id:\n"; $WIN32 = 0; $CYGWIN = 1; LogSyslog "[ERROR] $id error-priority test"; LogSyslog "[WARN] $id warn-priority test"; } sub TestDriverSyslogWin32native() { Initialize(); my $id = "$LIB.TestDriverSyslogWin32native"; $debug = 1; print "$id:\n"; $WIN32 = 1; $CYGWIN = 0; LogSyslog "[ERROR] $id error-priority test"; my $path = $WIN32_SYSLOG_PATH; print "$path:\n", FileRead($path), "\n"; } sub TestDriverSyslogWin32() { Initialize(); my $id = "$LIB.TestDriverSyslogWin32"; TestDriverSyslogWin32cygwin(); TestDriverSyslogWin32native(); } sub TestDriverSyslogUnix() { Initialize(); my $id = "$LIB.TestDriverSyslogUnix"; $debug = 1; print "$id:\n"; $WIN32 = 0; $CYGWIN = 0; LogSyslog "[ERROR] $id error-priority test"; } sub TestDriverSyslog() { Initialize(); my $id = "$LIB.TestDriverSyslog"; if ( $WIN32 ) { TestDriverSyslogWin32(); } else { TestDriverSyslogUnix(); } } # **************************************************************************** # # DESCRIPTION # # Set common http headers # # INPUT PARAMETERS # # $req reference to LWP object # $host # # RETURN VALUES # # none # # **************************************************************************** sub HTTPheaderSet ( $ $ ) { my $id = "$LIB.HTTPheaderSet"; my ($req, $host) = @ARG; $req->header( "Host", $host ); $req->header( "Pragma", "no-cache"); $req->header( "Connection", "close"); } # **************************************************************************** # # DESCRIPTION # # Update new IP address. # # INPUT PARAMETERS # # %hash Hash containing the needed parameters # # RETURN VALUES # # ( $code, $message ) # # **************************************************************************** sub UpdateDynDns ( % ) { my $id = "$LIB.UpdateDynDns"; my %arg = @ARG; my $LOGIN = $arg{login}; my $PASS = $arg{pass}; my $CONNECT = $arg{connect}; my $HOST = $arg{host}; # This is reference to a \@LIST of host names my $IP = $arg{ip}; my $WILDCARD = $arg{wildcard}; my $MX = $arg{mx}; my $HOSTMX = $arg{hostmx}; my $SYSTEM = $arg{system}; my $OFFLINE = $arg{offline}; my $provider = $arg{provider}; my $port = $arg{port}; my $proxy = $arg{proxy}; if ( $debug ) { print "$id: INPUT "; print <proxy( http => $proxy ); } # This is old, do not use. Just a reminder. # # my $url2 = # "" # . "http://${LOGIN}:${PASS}\@${CONNECT}" # . "/nic/dyndns" # . "?action=edit&started=1&hostname=YES" # . "&host_id=$host" # . "&myip=$IP" # . "&wildcard=$WILDCARD" # . "&backmx=$MX" # ; # 2001-06 Specification my $url = "" . "http://${LOGIN}:${PASS}\@${CONNECT}" . "/nic/update" . "?system=$SYSTEM" . "&hostname=$host" # hostname=host,host,host.. . "&myip=$IP" . "&wildcard=$WILDCARD" . "&backmx=$MX" . "&offline=$OFFLINE" ; $url .= "&mx=$HOSTMX" if $HOSTMX; if ( $provider =~ /ovh/ ) { # mx,wildcard and backmx are not supported # https://www.ovh.com/manager/fr/manager.pl # # Also uses HTTPS $url = "" . "https://${LOGIN}:${PASS}\@${CONNECT}" . "/nic/update" . "?system=dyndns" . "&hostname=$host" # hostname=host,host,host.. . "&myip=$IP" ; } my $req = new HTTP::Request( 'GET', $url ); $req->user_agent( "Perl client $PROGNAME/$VERSION"); HTTPheaderSet $req, $CONNECT; $req->authorization_basic( $LOGIN, $PASS ); if ( $test or $debug ) { print $req->as_string; } my ($status, $code, $str); if ( not $test and IPvalidate $IP) { my $resp = $ua->request( $req ); my $return = $resp->as_string; ( $code, $str ) = StatusCodeParseDynDns( $return ); if ( $return =~ /^\d\d\d / ) { # Web server errors # 500 (Internal Server Error) Can't # connect to members.dyndns.org:80 (Timeout) $verb and print "$id: Net or web server error." . " Testing with ping $CONNECT.\n"; unless ( Ping $CONNECT ) { Log "$id: [ERROR] Ping failed." . " Check your network connections.\n"; } else { Log "$id: [PANIC] Hm, ping was good." . " Maybe HTTP upate protocol " . "string has changed.\n" } } if ( $verb ) { print "$return\n$str\n"; } $status = StatusCodeHandle $code, $str, -dyndns; } $debug and print "$id: RETURN [$status]\n"; $status, $str; } # **************************************************************************** # # DESCRIPTION # # Update new IP address. # # INPUT PARAMETERS # # %hash Hash containing the needed parameters # # RETURN VALUES # # $stat If false, IP should not be recorded as successful # update. # # **************************************************************************** sub UpdateNoip ( % ) { my $id = "$LIB.UpdateNoip"; my %arg = @ARG; my $LOGIN = $arg{login}; my $PASS = $arg{pass}; my $CONNECT = $arg{connect}; my $HOST = $arg{host}; # This is reference to a \@LIST of host names my $IP = $arg{ip}; my $WILDCARD = $arg{wildcard}; my $MX = $arg{mx}; my $HOSTMX = $arg{hostmx}; my $SYSTEM = $arg{system}; my $OFFLINE = $arg{offline}; my $GROUP = $arg{group}; my $proxy = $arg{proxy}; if ( $debug ) { print "$id: INPUT "; print <proxy( http => $proxy ); } # Use the IP 0.0.0.0 to make your host inaccessible to # other users on the internet. This is useful if you will be # going offline for an extended period of time. If someone else # gets your old IP your users will not go to your old IP # address. if ( $OFFLINE eq "YES" ) { $verb and print "$id: offline request, setting IP to 0.0.0.0"; $IP = "0.0.0.0"; } # todo: 2005-02-15. There seems to be another update script # at http://dynupdate.no-ip.com/ducupdate.php but that is used by the # official no-ip.com scipt. See Downoads => Linux my $url = "" . "http://${CONNECT}/" . "update.php" . "?username=${LOGIN}&pass=${PASS}&host=${host}" . "&ip=$IP" ; $url .= "&groupname=$GROUP" if $GROUP; $url .= "&mx=$HOSTMX" if $HOSTMX; my $req = new HTTP::Request( 'GET', $url ); $req->user_agent( "Perl client $PROGNAME/$VERSION"); HTTPheaderSet $req, $CONNECT; # no-ip does not use authorization. # # $req->authorization_basic( $LOGIN, $PASS ); if ( $test or $debug ) { print $req->as_string; } my ($status, $code, $str); if ( not $test and IPvalidate $IP) { my $resp = $ua->request( $req ); my $return = $resp->as_string; ( $code, $str ) = StatusCodeParseNoip( $return ); if ( $verb ) { print $return; print "\n$str\n"; } $status = StatusCodeHandle $code, $str, -noip; } $debug and print "$id: done.\n"; $status, $str; } # **************************************************************************** # # DESCRIPTION # # Update new IP address. # # INPUT PARAMETERS # # %hash Hash containing the needed parameters # # RETURN VALUES # # $stat If false, IP should not be recorded as successful # update. # # **************************************************************************** sub UpdateHNorg ( % ) { my $id = "$LIB.UpdateHNorg"; my %arg = @ARG; my $LOGIN = $arg{login}; my $PASS = $arg{pass}; my $CONNECT = $arg{connect}; my $HOST = $arg{host}; # This is reference to a \@LIST of host names my $IP = $arg{ip}; my $WILDCARD = $arg{wildcard}; my $MX = $arg{mx}; my $HOSTMX = $arg{hostmx}; my $SYSTEM = $arg{system}; my $OFFLINE = $arg{offline}; my $GROUP = $arg{group}; my $proxy = $arg{proxy}; if ( $debug ) { print "$id: INPUT "; print <<"EOF"; $id: INPUT values are: LOGIN = $arg{login} PASS = $arg{pass} CONNECT = $arg{connect} HOST = @{ $arg{host} } IP = $arg{ip} WILDCARD = $arg{wildcard} MX = $arg{mx} HOSTMX = $arg{hostmx} SYSTEM = $arg{system} OFFLINE = $arg{offline} provider = $arg{provider} port = $arg{port} proxy = $arg{proxy} EOF } my $ua = new LWP::UserAgent or die "$id: LWP::UserAgent failed $ERRNO"; $verb and print "$id: Updating IP $IP\n"; my $host = join ",", @$HOST; if ( $proxy ) { $debug and print "$id: Using PROXY [$proxy]\n"; $ua->proxy( http => $proxy ); } # Use the IP 0.0.0.0 to make your host inaccessible to # other users on the internet. This is useful if you will be # going offline for an extended period of time. If someone else # gets your old IP your users will not go to your old IP # address. if ( $OFFLINE eq "YES" ) { $verb and print "$id: offline request, setting IP to 0.0.0.0"; $IP = "0.0.0.0"; } my $url = "" . "http://${CONNECT}/" . "vanity/update/?VER=1" . "&IP=$IP" ; $url .= "&mx=$HOSTMX" if $HOSTMX; my $req = new HTTP::Request( 'GET', $url ); $req->user_agent( "Perl client $PROGNAME/$VERSION"); HTTPheaderSet $req, $CONNECT; $req->authorization_basic( $LOGIN, $PASS ); if ( $test or $debug ) { print $req->as_string; } my ($status, $code, $str); if ( not $test and IPvalidate $IP) { my $resp = $ua->request( $req ); my $return = $resp->as_string; ( $code, $str ) = StatusCodeParseHNorg( $return ); if ( $verb ) { print $return; print "\n$str\n"; } $status = StatusCodeHandle $code, $str, -hnorg; } $debug and print "$id: done.\n"; $status, $str; } # **************************************************************************** # # DESCRIPTION # # Write IP address to a file. does nothing if program is running # in test or query mode. # # INPUT PARAMETERS # # $file # $ip # # RETURN VALUES # # true If Written. # # **************************************************************************** sub RunUpdateIPWrite ( $$ ) { my $id = "$LIB.RunUpdateIPWrite"; my ($file, $ip) = @ARG; $debug and print "$id: INPUT file [$file] ip [$ip]\n"; # If Running in DEBUG mode, do it. # If running in test mode OR Query, don't do it my $stat; if ( (not $test and not $OPT_QUERY) or $debug ) { if ( IPvalidate $ip ) { $stat = FileWrite $file, undef, $ip; $debug and print "$id: saved last used IP Address\n"; } else { Log "Invalid IP address $ip"; } } $stat; } # **************************************************************************** # # DESCRIPTION # # Set up parameters and call Update # # INPUT PARAMETERS # # $ IP address # # RETURN VALUES # # $stat If false, the IP couldn't be updated and the IP should # not be recorded to a saved file. E.g if user tried to # update a wrong domain name, or wrong password, # then he can try again. # $msg Message string for the STAT. # # **************************************************************************** sub RunUpdate ( $ ) { my $id = "$LIB.RunUpdate"; my ($ip) = @ARG; $debug and print "$id: INPUT ip [$ip]\n"; local $ARG = $OPT_PROVIDER; my $status = 0; my $msg = ''; if ( /dyndns|ovh/ ) { my $port = 80; $port = 443 if /ovh/; # https my $connect = "members.dyndns.org"; $connect = "www.ovh.com" if /ovh/; ($status, $msg) = UpdateDynDns connect => $connect , ip => $ip , system => $OPT_SYSTEM , login => $OPT_LOGIN , pass => $OPT_PASS , host => \@OPT_HOST , wildcard => $OPT_WILDCARD , mx => $OPT_MX , hostmx => $OPT_HOSTMX , offline => $OPT_OFFLINE , provider => $OPT_PROVIDER , port => $port , proxy => $OPT_PROXY ; } elsif ( /noip/ ) { # no-ip does not support updating all of the features # from a client. E.g. You have to go to the Web page to # manage the wild card option. # # So, some of the sent parameters are not yet used. ($status, $msg) = UpdateNoip connect => "dynupdate.no-ip.com" , ip => $ip , system => $OPT_SYSTEM , login => $OPT_LOGIN , pass => $OPT_PASS , host => \@OPT_HOST , wildcard => $OPT_WILDCARD # Not supported, but send anyway , mx => $OPT_MX # Not supported, but send anyway , hostmx => $OPT_HOSTMX # Not supported, but send anyway , offline => $OPT_OFFLINE , group => $OPT_GROUP , proxy => $OPT_PROXY ; } elsif ( /hnorg/ ) { # no-ip does not support updating all of the features # from a client. E.g. You have to go to the Web page to # manage the wild card option. # # So, some of the sent parameters are not yet used. ($status, $msg) = UpdateHNorg connect => "dup.hn.org" , ip => $ip , system => $OPT_SYSTEM , login => $OPT_LOGIN , pass => $OPT_PASS , host => \@OPT_HOST , wildcard => $OPT_WILDCARD # Not supported, but send anyway , mx => $OPT_MX # Not supported, but send anyway , hostmx => $OPT_HOSTMX # Not supported, but send anyway , offline => $OPT_OFFLINE , group => $OPT_GROUP , proxy => $OPT_PROXY ; } else { die "$id: Unknown OPT_PROVIDER [$OPT_PROVIDER]"; } $status, $msg; } # **************************************************************************** # # DESCRIPTION # # Run checks before making update. # - It is safe to update ip, even if same, at least every 30 days # - If IP has changed, update immediately. # # INPUT PARAMETERS # # %hash Parameters # # RETURN VALUES # # true if updated # $code Status code from the remote site # only if update failed and it can be tried again. # $msg Status string (if update run) # # **************************************************************************** sub ProcessUpdateOne ( % ) { my $id = "$LIB.ProcessUpdateOne"; my %arg = @ARG; my $file = $arg{-file}; my $ip = $arg{-ip}; my $lastIP = $arg{-lastip}; $debug and print "$id: INPUT file [$file] ip [$ip] last [$lastIP]\n"; my $valid = IPvalidate $ip; $valid = 1 if $test and $debug; # Treat it as "okay" # For dyndns.org, the IP must be updated every 30 days # in order to keep the account active my ($oldFile, $days) = IsFileOld $file; my $new = "$ip $lastIP" !~ /nochange/; if ( $OPT_FORCE ) { $debug and print "$id: --force is active\n"; unless ( $oldFile or $new ) { print "$id: [WARN] Using --force while IP has not changed.\n"; } $new = -forced; } $new = -test if $test; # "test" should run all phases $debug and print "$id: IP [$ip] valid [$valid] last IP [$lastIP]\n"; my ($stat, $msg, $update); if ( $valid ) { if ( $oldFile or $new ) { ($stat, $msg) = RunUpdate $ip; if ( $stat ) { my $msg = "$id: [EXIT] Hm, update failed but according to " . "error [$stat] it should be okay to try again. " . "Error epxplanation is [$msg]. " . "To be on the safe side, check parameters and " . "wait 30 minutes before trying again. " . "If in doubt, run next call with --debug 1 " ; Log $msg; die $msg; } else { if ( $OPT_DAEMON ) { Log "[OK] updated IP $ip and saved it to $file\n"; } # Succeeded ok, so record this ip $update = RunUpdateIPWrite $file, $ip; } } } if ( not $new and not $oldFile ) { # - If same ip is updated too fast, warn user. # - In 2002 the expiration of an account took 35 days at # www.dyndns.org. if ($days < 1) { my $msg = "$id: [WARN] It is not allowed to update same IP " . "address twice [$ip]. " . "Trying to do so in a short period of time (< 15 min) " . "might possibly cause the provider to block the domain " . "for further attemps. " . "In case you know what your're doing and want to force update, " . "delete file $file and run program again\n" ; if ( $OPT_DAEMON ) { #todo: Hm. } else { Log $msg; } } } $update, $stat, $msg } # **************************************************************************** # # DESCRIPTION # # Process passed query options and print output to screen. # # INPUT PARAMETERS # # None. # # RETURN VALUES # # true If program should quit # # **************************************************************************** sub ProcessQueryRequests (%) { my $id = "$LIB.ProcessQueryRequests"; $debug and print "$id: START\n"; # .............................................. local functions ... my $file; sub InfoFile(); local *InfoFile = sub { my $id = "$id.InfoFile"; my $msg = "$id: [ERROR] option --ethernet missing"; die $msg unless $OPT_ETHERNET; die "$id: [ERROR] option --provider missing" unless $OPT_PROVIDER; unless ( $file ) { $debug and print "$id:\n"; $file = IPfileNameGlobbed(); $file = IPfileNamePath $file, -absolute, \@OPT_HOST; $debug and print "$id: $file\n"; } }; my ($ip, $lastIP); sub Info(); local *InfoIP = sub { my $id = "$id.InfoIP"; unless ( $ip and $lastIP ) { $debug and print "$id:\n"; InfoFile() unless $file; ($ip, $lastIP) = GetIpAddressInfo -file => $file , -query => $OPT_QUERY ; $debug and print "$id: $ip, $lastIP\n"; } }; # ...................................................... queries ... my $stat; if ( defined $OPT_QUERY_IP_FILE ) { $debug and print "$id: Processing OPT_QUERY_IP_FILE\n"; InfoFile(); $debug and print "$id: Processing OPT_QUERY_IP_FILE\n"; print "$file\n"; $stat = -queryfile; } if ( defined $OPT_QUERY_IP_SAVED ) { $debug and print "$id: Processing OPT_QUERY_IP_SAVED\n"; InfoFile(); $lastIP = GetIpAddressLast( $file ); $debug and print "$id: Processing OPT_QUERY_IP_SAVED\n"; print "$lastIP\n"; $stat = -querysaved; } if ( $OPT_QUERY ) { # $ip = GetIpAddress() unless $ip; $debug and print "$id: Processing OPT_QUERY\n"; InfoIP(); $debug and print "$id: Processing OPT_QUERY\n"; print "$ip $lastIP\n"; $stat = -queryip; } if ( $OPT_QUERY_IP_CHANGED !~ /^-/ ) # '-undef' would mean "not used" { $debug and print "$id: Processing OPT_QUERY_IP_CHANGED\n"; InfoIP(); warn "$id: [WARN] --file* or --config option is missing" unless $file; unless ( IPvalidate $ip ) { die "$id: Cannot determine query. Current IP [$ip] " , "is not valid for Internet. " , "Do you need to add --urlping* option for router?" ; } my %code = ( changed => [ 0, "changed" ] , same => [ 1, "nochange" ] ); my @ret = @{ $code{changed} }; # set default value to "changed" InfoFile(); # We need to know if file is OLD my ($oldFile, $days) = IsFileOld $file; if ( ( $ip eq $lastIP or $lastIP =~ /^[a-z]/ ) # 'nochange' and not $oldFile ) { @ret = @{ $code{same} }; } # It depends how user wants our notifications of the change. # If he requested that shell exit status shuld be set, then # do explicit exit(). Other than that, print a message. my $exit = 1 if $OPT_QUERY_IP_CHANGED =~ /exit/i; my $ret = $ret[1]; $ret = $ret[0] if $exit; $debug and print "$id: Processing OPT_QUERY_IP_CHANGED\n" , "$id: ipchange check; return [$ret] => [@ret]\n" , "$id: days old [$days]\n" ; exit $ret if $exit; my $ipmaybe = ($ret =~ /^change/i) ? " $ip" : ""; printf "$ret %d%s\n", int $days, $ipmaybe; $stat = -querysameip } $debug and print "$id: return [$stat]\n"; $stat; } # **************************************************************************** # # DESCRIPTION # # Start update process. # # INPUT PARAMETERS # # $file [optional] Configuraton file being processed. # # RETURN VALUES # # None # # **************************************************************************** sub ProcessUpdateStart (; $) { my $id = "$LIB.ProcessUpdateStart"; my ($conf) = @ARG; $debug and print "$id: CONF [$conf]\n"; my $file = IPfileNameGlobbed(); $file = IPfileNamePath $file, -absolute, \@OPT_HOST; $debug and print "$id: Continuing update with file [$file] ...\n"; # The result of this call is two words: 81.197.0.2 nochange # The "nochange" is included if ip has not changed. my ($ip, $lastIP) = GetIpAddressInfo -file => $file , -query => $OPT_QUERY ; $debug and print "$id: OPT_PROVIDER $OPT_PROVIDER, file [$file]\n"; my $ok = VariableCheckMinimum $conf; if ( $ok ) { FileWriteCheckIP $file; ProcessUpdateOne -file => $file , -ip => $ip , -lastip => $lastIP ; } else { Log "FATAL: Too few options set. " . "Use --debug to see what is missing\n"; } }; # **************************************************************************** # # DESCRIPTION # # Read settings from each configuration file (if supplied) # and Process an update request. # # INPUT PARAMETERS # # %hash Parameters # # RETURN VALUES # # $quit If true, program should quit. # # **************************************************************************** sub ProcessUpdateMain ( % ) { my $id = "$LIB.ProcessUpdateMain"; my %arg = @ARG; my $configArrRef = $arg{-config}; $debug and print "$id: START\n"; my $stat; sub ProcessIt(; $); local *ProcessIt = sub { my $id = "$id.ProcessIt"; my ($conf) = @ARG; $debug and print "$id: Reading conf [$conf]\n"; $stat = ProcessQueryRequests(); unless ( $stat ) { ProcessUpdateStart $conf; } }; if ( defined $configArrRef and @$configArrRef ) { for my $file ( @$configArrRef ) { $debug and print "$id: processing config [$file]\n"; ConfigFileRead $file or next ; $debug and print "$id: processing config [$file]\n"; VariableCheckValidity $file; ProcessIt($file); } } else { $debug and print "$id: No config file. Using Cmd line options\n"; ProcessIt(); } $stat; } # **************************************************************************** # # DESCRIPTION # # Main entry point. If option --daemon is set, this function # never ends. # # INPUT PARAMETERS # # none # # RETURN VALUES # # none # # **************************************************************************** sub Main () { InitializeModules(); HandleCommandLineArgsMain(); VariableCheckValidity(); my $id = "$LIB.main"; $debug and print "$id: " . Version() . "\n"; if ( exists $ENV{DYNDNS_PL_CFG} ) { # Older versions of this program used a single file to # store the IP address. The variable is no longer read. warn "$PROGRAM_NAME: [UPGRADE NOTE] Non-supported environment " , "variable DYNDNS_PL_CFG found. Please migrate to the " , "new system. See --config and section 'CONFIGURATION FILE' " , "from the manual page"; } my @configFiles = @OPT_CONFIG_FILE; @configFiles = FileGlob @configFiles if @configFiles; $debug and print "$id: Config files [@configFiles]\n"; while ( 1 ) { my $stat = ProcessUpdateMain -config => \@configFiles; $debug and print "$id: loop daemon [$OPT_DAEMON] stat [$stat]\n"; exit 0 if $stat; if ( $OPT_DAEMON ) { $debug and print "$id: [daemon mode] sleeping $OPT_DAEMON minutes.\n"; if ( $OPT_DAEMON < $DAEMON_MIN ) { # Prevent from errors. The update must not be less. $OPT_DAEMON = $DAEMON_MIN; } sleep 60 * $OPT_DAEMON; next; } $debug and print "$id: loop normal EXIT\n"; exit 0; } } sub TestMain () { # This is only for developers. Uncomment lines to run test cases. TestDriver(); die; # TestDriverLinksysBEFW11S4(); die; # TestDriverLinksysBEFW11S4v4(); die; # TestDriverLinksysWRT54GL(); die; # TestDriverSyslog(); die; # TestDriverHNorg(); die; } Initialize(); # TestMain(); Main(); # End of file dyndns-2012.0112/doc/000077500000000000000000000000001170362450400140705ustar00rootroot00000000000000dyndns-2012.0112/doc/Makefile000066400000000000000000000031111170362450400155240ustar00rootroot00000000000000# # Copyright information # # Copyright (C) 2003-2012 Jari Aalto # # License # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details at # Visit . # # Description # # Rules for maintenance .SUFFIXES: .SUFFIXES: .pl .1 .html .txt # Pod generates .x~~ extra files # # $< = name of the input (full) # $@ = name, but only basename part, without suffix # $(*D) = macro; Give only directory part # $(*F) = macro; Give only file part PL = ../bin/dyndns.pl ../bin/dyndns.1: $(PL) perl $? --Help-man > $@ manual/index.html: $(PL) perl $? --Help-html > $@ rm -f *.tmp manual/index.txt: $(PL) pod2text $? > $@ index.txt: index.html lynx -dump $? > $@ # Rule: man: generate manual page man: ../bin/dyndns.1 # Rule: doc: generate documentation doc: index.txt manual/index.html manual/index.txt # Rule: www: copy web pages to ../../-www www: doc name=$$(basename $$(cd .. && pwd)); \ to=../../$$name-www; \ echo "Copying to $$to"; \ find . -type f -name "*.html" | \ rsync $${test:+"--dry-run"} \ --files-from=- \ --update \ --progress \ --verbose \ -r \ . \ $$to/ # End of file dyndns-2012.0112/doc/index.html000066400000000000000000000127731170362450400160770ustar00rootroot00000000000000 Perl Dynamic DNS (DDNS) Client Project
Perl Dynamic DNS (DDNS) Client Project

Links and download

Note: that the most up to date version is in version control. See development page instructions how get latest source code.

What is a Perl DDNS?

Perl client for updating a dynamic DNS IP information at supported providers (e.g. www.dyndns.org, www.no-ip.com). The dynamic DNS service allows mapping a dynamic IP address to a static hostname. This way the computer can be referred by name instead of ever changing IP address from ISP's pool.

In short, call the program at regular intervals (say every 6 hours):

  dyndns.pl --Provider dyndns --login LOGIN --pass PASSWORD --Host yourhost.dyndns.org

Platform Support

Supported OS platforms: Win32 native (Windows 9x/NT/2000/XP/*), Win32 Cygwin (Unix like), Linux (Redhat, Debian). Other distributions not tested. Should work with any FHS compliant Linux distributions as well as BSD provided that command ifconfig(1) is available.

Contact

There is no mailing list for the project. See Development page above how to contact maintainer and submit feature requests and bug reports.


GNU GPL All files in this project are licensed under GNU GPL. Savannah Logo This project, as well as many other projects is hosted by Savannah.
Savannah Logo W3C CSS logo W3 validated.
dyndns-2012.0112/doc/index.txt000066400000000000000000000051441170362450400157440ustar00rootroot00000000000000 __________________________________________________________________ Perl Dynamic DNS (DDNS) Client Project __________________________________________________________________ Links and download Note: that the most up to date version is in version control. See development page instructions how get latest source code. * [1]Main project page (never changes; bookmark this one) * [2]Development page (Downloads, Source code, bug tracker etc.) * [3]Manual (Documentation) * [4]ChangeLog Generated by editing the code in Emacs and pressing key binding (C-x 4 a). What is a Perl DDNS? Perl client for updating a dynamic DNS IP information at supported providers (e.g. [5]www.dyndns.org, [6]www.no-ip.com). The dynamic DNS service allows mapping a dynamic IP address to a static hostname. This way the computer can be referred by name instead of ever changing IP address from ISP's pool. In short, call the program at regular intervals (say every 6 hours): dyndns.pl --Provider dyndns --login LOGIN --pass PASSWORD --Host yourhost.dynd ns.org Platform Support Supported OS platforms: Win32 native (Windows 9x/NT/2000/XP/*), Win32 [7]Cygwin (Unix like), Linux (Redhat, Debian). Other distributions not tested. Should work with any [8]FHS compliant Linux distributions as well as BSD provided that command ifconfig(1) is available. Contact There is no mailing list for the project. See Development page above how to contact maintainer and submit feature requests and bug reports. __________________________________________________________________ [9]GNU GPL All files in this project are licensed under [10]GNU GPL. [11]Savannah Logo This project, as well as many other projects is hosted by [12]Savannah. [13]Savannah Logo [14]W3C CSS logo [15]W3 validated. References 1. http://freecode.com/projects/perl-dyndns 2. https://savannah.nongnu.org/projects/perl-dyndns 3. file://localhost/home/jaalto/vc/project/sforge/perl-dyndns/doc/manual/ 4. http://git.savannah.gnu.org/gitweb/?p=perl-dyndns.git;a=blob;f=bin/ChangeLog;hb=HEAD 5. http://www.dydns.org/ 6. http://www.no-ip.com/ 7. http://www.cygwin.com/ 8. http://www.pathname.com/fhs 9. http://www.gnu.org/licenses 10. http://www.gnu.org/licenses/ 11. http://www.sanannah.org/ 12. http://www.savannah.org/ 13. http://validator.w3.org/check?uri=referer 14. http://jigsaw.w3.org/css-validator/validator?uri=referer 15. http://www.w3.org/ dyndns-2012.0112/doc/license/000077500000000000000000000000001170362450400155125ustar00rootroot00000000000000dyndns-2012.0112/doc/license/COPYING.GNU-FDL000066400000000000000000000476631170362450400176200ustar00rootroot00000000000000 GNU Free Documentation License Version 1.2, November 2002 Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements". 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. dyndns-2012.0112/doc/license/COPYING.GNU-GPL000066400000000000000000000431031170362450400176160ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dyndns-2012.0112/doc/license/LICENSE.txt000066400000000000000000000034141170362450400173370ustar00rootroot00000000000000Licensing information This program runs solely with Free Software. It does not rely on any component of non-Free Software. Copyright (C) 1999-2012 Jari Aalto This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at Visit for more information - - Exception: The files under directory doc/ are DUAL LICENCED and may be distributed under the terms of GNU General Public License (GNU GPL) --see above--; *or*, at your option, distributed under the terms of GNU Free Documentation License (GNU FDL). The end user can continue to distribute the documentation in this dual licence form *or* select the other license (GNU GPL, GNU FDL) and remove the unwanted one. Copyright (C) 1999-2012 Jari Aalto Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. See GNU Free Documentation License for more details at Visit . End dyndns-2012.0112/doc/manual/000077500000000000000000000000001170362450400153455ustar00rootroot00000000000000dyndns-2012.0112/doc/manual/index.html000066400000000000000000001142451170362450400173510ustar00rootroot00000000000000 dyndns - Update IP address to dynamic DNS provider


NAME

dyndns - Update IP address to dynamic DNS (DDNS) provider


SYNOPSIS

    dyndns --login LOGIN --password PASSWORD \
           --host yourhost.dyndns.org


DESCRIPTION

A cross platform Perl client for updating dynamic DNS IP information at supported providers (see --provider). By Default this program expects www.dyndns.org provider.

The dynamic DNS services allow mapping a dynamic IP address to a static hostname. This way the host can be refered by name instead of the changing IP address from the ISP's pool. Some DDNS providers offer a single account and a single host namefree of charge. Please check the information from the Providers' pages.

Separate files are used for remembering the last IP address to prevent updating the same IP address again. This is necessary in order to comply guidelines of the providers where multiple updates of the same IP address could cause your domain to be blocked. You should not normally need to touch the files where the IP addresses are stored.

If you know what you are doing and desperately need a forced update, delete the IP files and start program with apropriate arguments. Without the information about previous IP address, program sends a new update request to the provider.

Program has been designed to work under any version of Windows or Linux, possibly Mac OS included. It may not work under other Unix/BSD variants. Please see BUGS section how to provide details to add support for other operating systems.

Visit the page of the provider and create an account. Write down the login name, password and host name you registered.

For Windows operating systems, you need to install Perl. There are two Perl incarnatons: Native Windows version (Activestate Perl) and Cygwin version. The http://www.cygwin.com/ is recommended as it more closely follows the original Perl environment.


OPTIONS

Gneneral options

--config=FILE [--config=FILE ...]

List of configuration files to read. No command line options other than --verbose, --debug or --test should be appended or results are undefined. Each file must contain complete DDNS account configuration.

The FILE part will go through Perl's glob() function, meaning that the filenames are expanded. Series of configuration files can be run at once e.g. within directory /etc/dyndns/ by using a single option. The order of the files processed is alphabetical:

    --config=/etc/dyndns/*

See section CONFIGURATION FILE for more information how to write the files.

--host=host1 [--host=host2 ...]

Use registered HOST(s).

--group GROUP

This option is only for --provider noip

Assign IP to GROUP. Do you have many hosts that all update to the same IP address? Update a group instead of a many hosts.

--login LOGIN

DDNS account's LOGIN name.

--mxhost MX-HOST-NAME

This option is only for --provider dyndns

Update account information with MX hostname. Specifies a Mail eXchanger for use with the host being modified. Must resolve to an static IP address, or it will be ignored. If you don't know DNS, don't touch this option.

The servers you list need to be correctly configured to accept mail for your hostname, or this will do no good. Setting up a server as an MX without permission of the administrator may get them angry at you. If someone is contacted about such an infraction, your MX record will be removed and possibly further action taken to prevent it from happening again. Any mail sent to a misconfigured server listed as an MX may bounce, and may be lost.

--mx-option

This option is only for --provider dyndns

Turn on MX option. Request that the MX in the previous parameter be set up as a backup. This means that mail will first attempt to deliver to your host directly, and will be delivered to the MX listed as a backup.

Note regarding provider noip:

Update clients cannot change this value. Clients can only submit requests to the php script to update the A record. Changes such as MX records must be done through website.

--offline

If given, set the host to offline mode.

Note: [dyndns] This feature is only available to donators. The "!donator" return message will appear if this is set on a non-donator host.

This is useful if you will be going offline for an extended period of time. If someone else gets your old IP your users will not go to your old IP address.

--password PASSWORD

DDNS account's PASSWORD.

--system {dyndns|statdns|custom}

This option is only for --provider dyndns

The system you wish to use for this update. dyndns will update a dynamic host, custom will update a MyDynDNS Custom DNS host and statdns will update a static host. The default value is dyndns and you cannot use other options (statdns|custom) unless you donate and gain access to the more advanced features.

See the DDNS provider's pages for more information.

--wildcard

Turn on wildcard option. The wildcard aliases *.yourhost.ourdomain.ext to the same address as yourhost.ourdomain.ext

Additional options

-D, --daemon [WAIT-MINUTES]

Enter daemon mode. The term "daemon" refers to a standalone processes which keep serving until killed. In daemon mode program enters into infinite loop where IP address changes are checked periodically. For each new ip address check, program waits for WAIT-MINUTES. Messages in this mode are reported using syslog(3); if available.

This option is designed to be used in systems that do not provide Unix-like cron capabilities (e.g under Windows OS). It is better to use cron(8) and define an entry using crontab(5) notation to run the update in periodic intervals. This will use less memory when Perl is not permanently kept in memory like it would with option --daemon.

The update to DDNS provider happens only if

    1) IP address changes
    2) or it has taken 30 days since last update.
       (See DDNS providers' account expiration time documentation)

The minimum sleep time is 5 minutes. Program will not allow faster wake up times(*). The value can be expressed in formats:

    15      Plain number, minutes
    15m     (m)inutes. Same sa above
    1h      (h)ours
    1d      (d)days

This options is primarily for permanent Internet connection. If you have a dial-up connection, it is better to arrange the IP update at the same time as when the connection is started. In Linux this would happen during ifup(1).

(*) Perl language is CPU intensive so any faster check would put considerable strain on system resources. Normally a value of 30 or 60 minutes will work fine in most cases. Monitor the ISP's IP rotation time to adjust the time in to use sufficiently long wake up times.

--ethernet [CARD]

In Linux system, the automatic IP detection uses program ifconfig(1). If you have multiple network cards, select the correct card with this option. The default device used for query is eth0.

--file PREFIX

Prefix where to save IP information. This can be a) a absolute path name to a file b) directory where to save or c) directory + prefix where to save. Make sure that files in this location do not get deleted. If they are deleted and you happen to update SAME ip twice within a short period - according to www.dyndns.org FAQ - your address may be blocked.

On Windows platform all filenames must use forward slashs like C:/somedir/to/, not C:\somedir\to\.

The PREFIX is only used as a basename for supported DDNS accounts (see --provider). The saved filename is constructed like this:

   PREFIX<ethernet-card>-<update-system>-<host>-<provider>.log
                          |
                          See option --system

A sample filename in Linux could be something like this if PREFIX were set to /var/log/dyndns/:

    /var/log/dyndns/eth0-statdns-my.dyndns.org-dyndns.log
-f, --file-default

Use reasonable default for saved IP file PREFIX (see --file). Under Windows, %WINDIR% is used. Under Linux the PREFIXes searched are

    /var/log/dyndns/     (if directory exists)
    /var/log/            (system's standard)
    $HOME/tmp or $HOME   If process is not running under root

This options is by default activated if --file is not in use.

--proxy HOST

Use HOST as outgoing HTTP proxy.

-P, --provider TYPE

By default, program connects to dyndns.org to update the dynamic IP address. There are many free dynamic DNS providers are reported. Supported list of TYPES in alphabetical order:

    hnorg       No domain name limists
                Basic DDNS service is free (as of 2003-10-02)
                http://hn.org/
    dyndns      No domain name limits.
                Basic DDNS service is free (as of 2003-10-02)
                http://www.dyndns.org/
                See also http://members.dyndns.org/
    noip        No domain name limits.
                Basic DDNS service is free (as of 2003-10-02)
                http://www.no-ip.com/

NOTE: as of 2010, the support for sites of hnorg, noip is probably non-working due to changes in the interfaces. Please use only dyndns at this time.

--query

Query current IP address and quit. Note: if you use router, you may need --urlping* options, otherwise the IP address returned is your subnet's DHCP IP and not the ISP's Internet IP.

Output of the command is at least two string. The second string is last-ip-info-not-available if the saved ip file name is not specified. In order to program to know where to look for saved IP files you need to give some --file* or --config option. The second string can also be nochange if current IP address is same as what was found from saved file. Examples:

    100.197.1.6 last-ip-info-not-available
    100.197.1.6 100.197.1.7
    100.197.1.6 nochange 18
                         |
                         How many days since last saved IP

Note for tool developers: additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right.

--query-ipchanged ['exitcode']

Print message if IP has changed or not. This option can take an optional string argument exitcode which causes program to indicate changed ip address with standard shell status code (in bash shell that would available at variable $?):

    $ dyndns --query-ipchange exitcode --file-default \
      --provider dyndns --host xxx.dyndns.org
    $ echo $?
    ... the status code of shell ($?) would be:
    0   true value, changed
    1   false value, error code, i.e. not changed

Without the exitcode argument, the returned strings are:

                Current IP address
                |
    changed  35 111.222.333.444
    nochange 18
             |
             Days since last IP update. Based on saved IP file's
             time stamp.

If the last saved IP file's time stamp is too old, then even if the IP were not really changed, the situation is reported with word changed. This is due to time limits the DDNS providers have. The account would expire unless it is updated in NN days.

Note for tool developers: additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right.

--query-ipfile

Print the name of the IP file and quit.

Note: In order for this option to work, you must supply all other options would be normally pass to update the DDNS account, because the Ip filename depends on these options. Alternatively provide option --config FILE from where all relevant information if read.

    --ethernet      [optional, defaults to eth0]
    --provider      [optional, defaults to dyndns]
    --system        [optional, defaults to dyndns]
    --host          required.

Here is an example which supposed that directory /var/log/dyndns/ already exists:

    $ dyndns --file-default --query-ipfile \
      --provider dyndns --host xxx.dyndns.org
    /var/log/dyndns/eth0-dyndns-dyndns-xxx-dyndns.org.log
--regexp REGEXP

In host, which has multiple netword cards, the response can include multiple IP addresses. The default is to pick always the first choice, but that may not be what is wanted. The regexp MUST not contain capturing parentheses: if you need one, use non-capturing choice (?:). Refer to Perl manual page perlre for more information about non-cpaturing regular expression parentheses.

Here is an example from Windows:

    Ethernet adapter {3C317757-AEE8-4DA7-9B68-C67B4D344103}:
        Connection-specific DNS Suffix  . :
        Autoconfiguration IP Address. . . : 169.254.241.150
        Subnet Mask . . . . . . . . . . . : 255.255.0.0
        Default Gateway . . . . . . . . . :
    Ethernet adapter Local Area Connection 3:
        Connection-specific DNS Suffix  . : somewhere.net
        IP Address. . . . . . . . . . . . : 193.10.221.45
        Subnet Mask . . . . . . . . . . . : 255.255.0.0
        Default Gateway . . . . . . . . . : 10.10.0.101

The 193.10.221.45 is the intended dynamic IP address, not the first one. To instruct searching from somewhere else in the listing, supply a regular expressions that can match a portion in the listing after which the IP address appears. In the above case, the regexp could be:

    --regexp "Connection 3:"

In Windows, the words that follow "IP Address" are automatically expected, so you should not add them to the regexp.

In FreeBSD 4.5, you may get following response:

    tun0: flags <UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1492
        inet6 fe80::250:4ff:feef:7998%tun0 prefixlen 64 scopeid 0x7
        inet 62.214.33.49 --> 255.255.255.255 netmask 0xffffffff
        inet 62.214.32.12 --> 255.255.255.255 netmask 0xffffffff
        inet 62.214.35.49 --> 255.255.255.255 netmask 0xffffffff
        inet 62.214.33.163 --> 62.214.32.1 netmask 0xff000000
        Opened by PID 64

The correct IP address to pick from the listing is the one, which does not contain netmask 0xffffffff. The picked address for above is therefore 62.214.33.163. The regexp that finds that line is:

    --regexp ".*0xffffffff.*?inet"
               |            |
               |            Search minimum match until word "inet"
               search maximum match

This will match all the way until the the last line with netmask 0xffffffff, after which shortest match .*? to inet is reached to read the number following it. The regexp must make sure that the next word after its match point is the wanted address.

Cable, DSL and router options

If you do not have direct access to world known real IP address, but to a subnet IP address, then you cannot determine your outside world IP address from your machine directly. See picture below:

                        router/subnet                    Internet
                       +-------------+                +-----------+
   Your PC:            |             | maps address   |           |
   connect to ISP -->  | ROUTER      | -------------> |           |
                       | 192.168.... |                | 80.1.1.1  |
   local ip says:      +-------------+                +-----------+
   192.168.xxx.xxx                                    THE REAL IP

ASDL and cable modem and other connections may not be directly connected to Internet, but to a router to allow subnnetting internal hosts. This makes several computers to access the Internet while the ISP has offered only one visible IP address to you. The router makes the mapping of the local subnet IP to the world known IP address, provided by the ISP when the connection was established.

You need some way to find out what is the real IP is. The simplest way is to connect to a some web page, which runs a reverse lookup service which can show the connecting IP address.

Note: the following web web page does not exists. To find a service that is able to display your IP address, do a google search. Let's say, that you found a fictional service http://www.example.com/showip and somewhere in the web page it reads:

        Your IP address is: 212.111.11.10

This is what you need. To automate the lookup from web page, you need to instruct the program to connect to URL page and tell how to read the ip from page by using a regular expression. Consult Perl's manual page perlre if you are unfamiliar with the regular expressions. For the above fictional service, the options needed would be:

    --urlping         "http://showip.org/?showit.pl";
    --urlping-regexp  "address is:\s+([\d.]+)"
                                  |  ||
                                  |  |+- Read all digits and periods
                                  |  |
                                  |  +- capturing parentheses
                                  |
                                  +- expect any number of whitespaces

NOTE: The text to match from web page is not text/plain, but text/html, so you must look at the HTML page's sources to match the IP address correctly without the bold <b> tags etc.

--urlping URL

Web page where world known IP address can be read. If you find a Web server that is running some program, which can show your IP addres, use it. The example below connects to site and calls CGI program to make show the connector's IP address. Be polite. Making calls like this too often may cause putting blocks to your site.

    http://www.dyndns.org/cgi-bin/check_ip.cgi

Be sure to use period of 60 minutes or more with --daemon option to not increase the load in the "ping" site and cause admin's to shut down the service.

--urlping-dyndns

Contact http://www.dyndns.org service to obtain IP address information. This is shorthand to more general optiopn --urlping.

--urlping-linksys [TYPE]

Specialized router option for Linksys products.

This option connects to Linksys Wireless LAN 4-point router, whose page is by default at local network address -<http://192.168.1.1/Status.htm>. The world known IP address (which is provided by ISP) is parsed from that page. The product is typically connected to the cable or DSL modem. Refer to routing picture presented previously.

If the default login and password has been changed, options --urlping-login and --urlping-password must be supplied

For TYPE information, See <http://www.linksys.com/>. Products codes currently supported include:

 - BEFW11S4, Wireless Access Point Router with 4-Port Switch.
   Page: http://192.168.1.1/Status.htm
 - WRT54GL, Wireless WRT54GL Wireless-G Broadband Router.
   Page: http://192.168.1.1/Status_Router.asp
--urlping-login LOGIN

If --urlping web page requires authentication, supply user name for a secured web page.

--urlping-password LOGIN

If --urlping web page requires authentication, supply password for a secured web page.

--urlping-regexp REGEXP

After connecting to page with --urlping URL, the web page is examined for REGEXP. The regexp must catch the IP to perl match $1. Use non-capturing parenthesis to control the match as needed. For example this is incorrect:

    --urlping-regexp "(Address|addr:)\s+([0-9.]+)"
                      |                 |
                      $1                $2

The match MUST be in "$1", so you must use non-capturing perl paentheses for the first one:

    --urlping-regexp "(?:Address|addr:) +([0-9.]+)"
                       |                 |
                       non-capturing     $1

If this option is not given, the default value is to find first word that matches:

    ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)

Miscellaneous options

--debug [LEVEL]

Turn on debug with optional positive LEVEL. Use this if you want to know details how the program initiates connection or if you experience trouble contacting DDNS provider.

--help

Print help

--help-html

Print help in HTML format.

--help-man

Print help page in Unix manual page format. You want to feed this output to nroff -man in order to read it.

--test [LEVEL]

Run in test mode, do not actually update anything. LEVEL 1 allows sending HTTP ping options and getting answers.

--test-driver

This is for developer only. Run internal integrity tests.

--test-account

This is for developer only. Uses DYNDNS test account options. All command line values that set host information or provider are ignored. Refer to client page at http://clients.dyndns.org/devel

--verbose

Print informational messages.

--version

Print version and contact information.


EXAMPLES

To update IP address periodically, use crontab(5) entry. The update will happen only if IP has changed since last time:

    0 0-23 * * * perl <absolute path>/dyndns <options>

To check current IP address:

  dyndns --query [--urlping...]
                 |
                 Select correct option to do the "ping" for IP

Show where the ip file is/would be stored with given connect options. The option --file-default uses OS's default directory structure.

  dyndns --file-default --query-ipfile --provider dyndns \
          --host xxx.dyndns.org

To upate account information to DDNS provider:

  dyndns --provider dyndns --login <login> --password <pass> --host your.dyndns.org

If your router can display a web page containing the world known IP address, you can instruct to "ping" it. Suppose that router is at address 192.168.1.1 and page that displays the world known IP is status.html, and you have to log in to the router using username foo and password bar:

  dyndns --urlping http://192.168.1.1/Status.html \
         --urlping-login foo                      \
         --urlping-pass  bar                      \

If the default regexp does not find IP address from the page, supply your own match with option --urlping-regexp. In case of doubt, add option --debug 1 and examine the responses. In serious doubt, contact the maintainer (see option --version) and send the full debug output.

Tip: if you run a local web server, provider www.dyndns.org can direct calls to it. See option --wildcard to enable `*.your.dyndns.org' domain delegation, like if it we accessed using `www.your.dyndns.org'.


CONFIGURATION FILE

Instead of supplying options at command line, they can be stored to a configuration file. For each DDNS account and different domains, a separate configuration file must be created. The configuration files are read with option --config.

The syntax of the configuration file includes comments that start with (#). Anything after hash-sign is interpreted as comment. Values are set in KEY = VALUE fashion, where spaces are non-significant. Keys are not case sensitive, but values are.

Below, lines marked with [default] need only be set if the default value needs to be changed. Lines marked with [noip] or [dyndns] apply to only those providers' DDNS accounts. Notice that some keys, like host, can take multple values seprated by colons. On/Off options take values [1/0] respectively. All host name values below are fictional.

    # /etc/dyndns/dyndns.conf
    #  Set to "yes" to make this configuration file excluded
    #  from updates.
    disable  = no       # [default]
    ethernet = eth0     # [default]
    group    = mygourp  # Provider [noip] only.
    host     = host1.dyndns.org, host1.dyndns.org
    #   If you route mail. See dyndns.org documentation for details
    #   how to set up MX records. If you know nothing about DNS/BIND
    #   Don't even consider using this option. Misuse or broken
    #   DNS at your end will probably terminate your 'free' dyndns contract.
    mxhost   = mxhost.dyndns.org
    #   Details how to get the world known IP address, in case the standard
    #   Linux 'ifconfig' or Windows 'ipconfig' programs cannot be used. This
    #   interests mainly Cable, DSL and router owners. NOTE: You may
    #   not use all these options. E.g. [urlping-linksys4] is alternate
    #   to [urlping] etc. See documentation.
    urlping-linksys  = BEFW11S4
    urlping-login    = joe
    urlping-password = mypass
    urlping          = fictional.showip.org
    urlping-regexp   = (?:Address|addr:)\s+([0-9.]+)
    #   Where IPs are stored. Directory name or Directory name with
    #   additional file prefix. The directory part must exist. You could
    #   say 'file = /var/log/dyndns/' but that's the default.
    file     = default              # Use OS's default location
    #   The DDNS account details
    login    = mylogin
    password = mypass
    provider = dyndns               # [default]
    proxy    = myproxy.myisp.net    # set only if needed for HTTP calls
    #   Hou need this option only if you have multiple ethernet cards.
    #   After which regexp the IP number appers in ifconfig(1) listing?
    regexp   = .*0xffffffff.*?inet
    #   What account are you using? Select 'dyndns|statdns|custom'
    system   = dyndns               # Provider [dyndns] only
    #   Yes, delegate all *.mydomain.dyndns.org calls
    wildcard = 1
    # End of cnfiguration file

See the details of all of these options from the corresponding command line option descriptions. E.g. option 'ethernet' in configuration file corresponds to --ethernet command line option. The normal configuration file for average user would only include few lines:

    # /etc/dyndns/myhost.dyndns.org.conf
    host             = myhost.dyndns.org
    file             = default      # Use OS's default location
    login            = mylogin
    password         = mypassword
    provider         = dyndns
    system           = dyndns       # or 'statdns'
    wildcard         = 1            # Delegate *.mydomain.dyndns.org
    # End of cnfiguration file

TODO (write Debian daemon scripts) FIXME:

    update-rc.d dyndns start 3 4 5 6    # Debian


SUPPORT REQUESTS

For new Operating System, provide all relevant commands, their options, examples and their output which answer to following questions. The items in parentheses are examples from Linux:

    - How is the OS detected? Send result of 'id -a', or if file/dir
      structure can be used to detect the system. In Lunux the
      existence of /boot/vmlinuz could indicate that "this is a Linux
      OS".
    - What is the command to get network information (commandlike 'ifconfig')
    - Where are the system configuration files stored (in directory /etc?)
    - Where are the log files stored (under /var/log?)

To add support for routers that can be connected through HTTP protocol or with some other commands, please provide connection details and full HTTP response:

  wget -O <route-model>-dump.html http://192.168.1.0/your-network/router/page.html


TROUBLESHOOTING

1. Turn on --debug to see exact details how the program runs and what HTTP requests are sent and received.

2. Most of the <--query> options can't be used standalone. Please see documentation what additional options you need to supply with them.


ENVIRONMENT

TMPDIR

Directory of temporary files. Defaults to system temporary dir.


FILES

Daemon startup file

    /etc/default/dyndns

In Linux the syslog message files are:

    /etc/syslog.conf         daemon.err daemon.warning
    /var/log/daemon.log

There is no default location where program would search for configuration files. Configuration files may be found in directory /etc/dyndns/examples. It is recommended that the examples are modified and copied one directorory up in order to use option --config /etc/dyndns/*.

If program is run with Windows Activestate Perl, the log file is stored to file C:/syslog.txt.


EXIT STATUS

Not defined.


DEPENDENCIES

Uses standard Perl modules.

HTTP::Headers HTTP::Request::Common LWP::UserAgent LWP::Simple Sys::Syslog


STANDARDS

The dyndns provider's client specification is at https://www.dyndns.com/developers/specs/


BUGS AND LIMITATIONS

Cygwin syslog

There is no syslog daemon in Cygwin. The Cygwin POSIX emulation layer takes care about syslog requests. On NT and above systems it logs to the Windows's event manager, on Win9x and ME a file is created in the root of drive C:. See message <http://cygwin.com/ml/cygwin/2002-10/msg00219.html> for more details.

You can see the entries in W2K Start => Settings => Administrative Tools => Computer Management: [ System Tools / Event Viewer / Application ]

Debugging errors

Please use option --debug 2 and save the result. Contact maintainer if you find bugs or need new features.

About providers hnorg and noip

The program is primarily developed and maintained to support dyndns.org. The other providers haven't been tested since 2003.


SEE ALSO

syslog(3), Debian package ddclient(1)

See other client software at http://clients.dyndns.org


AVAILABILITY

http://freecode.com/projects/perl-dyndns


AUTHOR

This program is free software; you can redistribute and/or modify program under the terms of GNU General Public license either version 2 of the License, or (at your option) any later version.

The documentation may be distributed subject to the terms and conditions set forth in GNU General Public License v2 or later (GNU GPL); or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL).

dyndns-2012.0112/doc/manual/index.txt000066400000000000000000000766171170362450400172360ustar00rootroot00000000000000NAME dyndns - Update IP address to dynamic DNS (DDNS) provider SYNOPSIS dyndns --login LOGIN --password PASSWORD \ --host yourhost.dyndns.org DESCRIPTION A cross platform Perl client for updating dynamic DNS IP information at supported providers (see "--provider"). By Default this program expects www.dyndns.org provider. The dynamic DNS services allow mapping a dynamic IP address to a static hostname. This way the host can be refered by name instead of the changing IP address from the ISP's pool. Some DDNS providers offer a single account and a single host namefree of charge. Please check the information from the Providers' pages. Separate files are used for remembering the last IP address to prevent updating the same IP address again. This is necessary in order to comply guidelines of the providers where multiple updates of the same IP address could cause your domain to be blocked. You should not normally need to touch the files where the IP addresses are stored. If you know what you are doing and desperately need a forced update, delete the IP files and start program with apropriate arguments. Without the information about previous IP address, program sends a new update request to the provider. Program has been designed to work under any version of Windows or Linux, possibly Mac OS included. It may not work under other Unix/BSD variants. Please see BUGS section how to provide details to add support for other operating systems. Visit the page of the provider and create an account. Write down the login name, password and host name you registered. For Windows operating systems, you need to install Perl. There are two Perl incarnatons: Native Windows version (Activestate Perl) and Cygwin version. The "http://www.cygwin.com/" is recommended as it more closely follows the original Perl environment. OPTIONS Gneneral options --config=FILE [--config=FILE ...] List of configuration files to read. No command line options other than --verbose, --debug or --test should be appended or results are undefined. Each file must contain complete DDNS account configuration. The FILE part will go through Perl's "glob()" function, meaning that the filenames are expanded. Series of configuration files can be run at once e.g. within directory "/etc/dyndns/" by using a single option. The order of the files processed is alphabetical: --config=/etc/dyndns/* See section CONFIGURATION FILE for more information how to write the files. --host=host1 [--host=host2 ...] Use registered HOST(s). --group GROUP This option is only for --provider noip Assign IP to GROUP. Do you have many hosts that all update to the same IP address? Update a group instead of a many hosts. --login LOGIN DDNS account's LOGIN name. --mxhost MX-HOST-NAME This option is only for --provider dyndns Update account information with MX hostname. Specifies a Mail eXchanger for use with the host being modified. Must resolve to an static IP address, or it will be ignored. If you don't know DNS, don't touch this option. The servers you list need to be correctly configured to accept mail for your hostname, or this will do no good. Setting up a server as an MX without permission of the administrator may get them angry at you. If someone is contacted about such an infraction, your MX record will be removed and possibly further action taken to prevent it from happening again. Any mail sent to a misconfigured server listed as an MX may bounce, and may be lost. --mx-option This option is only for --provider dyndns Turn on MX option. Request that the MX in the previous parameter be set up as a backup. This means that mail will first attempt to deliver to your host directly, and will be delivered to the MX listed as a backup. Note regarding provider "noip": Update clients cannot change this value. Clients can only submit requests to the php script to update the A record. Changes such as MX records must be done through website. --offline If given, set the host to offline mode. "Note:" [dyndns] This feature is only available to donators. The "!donator" return message will appear if this is set on a non-donator host. This is useful if you will be going offline for an extended period of time. If someone else gets your old IP your users will not go to your old IP address. --password PASSWORD DDNS account's PASSWORD. --system {dyndns|statdns|custom} This option is only for --provider dyndns The system you wish to use for this update. "dyndns" will update a dynamic host, "custom" will update a MyDynDNS Custom DNS host and "statdns" will update a static host. The default value is "dyndns" and you cannot use other options (statdns|custom) unless you donate and gain access to the more advanced features. See the DDNS provider's pages for more information. --wildcard Turn on wildcard option. The wildcard aliases "*.yourhost.ourdomain.ext" to the same address as "yourhost.ourdomain.ext" Additional options -D, --daemon [WAIT-MINUTES] Enter daemon mode. The term "daemon" refers to a standalone processes which keep serving until killed. In daemon mode program enters into infinite loop where IP address changes are checked periodically. For each new ip address check, program waits for WAIT-MINUTES. Messages in this mode are reported using syslog(3); if available. This option is designed to be used in systems that do not provide Unix-like cron capabilities (e.g under Windows OS). It is better to use cron(8) and define an entry using crontab(5) notation to run the update in periodic intervals. This will use less memory when Perl is not permanently kept in memory like it would with option --daemon. The update to DDNS provider happens only if 1) IP address changes 2) or it has taken 30 days since last update. (See DDNS providers' account expiration time documentation) The minimum sleep time is 5 minutes. Program will not allow faster wake up times(*). The value can be expressed in formats: 15 Plain number, minutes 15m (m)inutes. Same sa above 1h (h)ours 1d (d)days This options is primarily for permanent Internet connection. If you have a dial-up connection, it is better to arrange the IP update at the same time as when the connection is started. In Linux this would happen during ifup(1). (*) Perl language is CPU intensive so any faster check would put considerable strain on system resources. Normally a value of 30 or 60 minutes will work fine in most cases. Monitor the ISP's IP rotation time to adjust the time in to use sufficiently long wake up times. --ethernet [CARD] In Linux system, the automatic IP detection uses program ifconfig(1). If you have multiple network cards, select the correct card with this option. The default device used for query is "eth0". --file PREFIX Prefix where to save IP information. This can be a) a absolute path name to a file b) directory where to save or c) directory + prefix where to save. Make sure that files in this location do not get deleted. If they are deleted and you happen to update SAME ip twice within a short period - according to www.dyndns.org FAQ - your address may be blocked. On Windows platform all filenames must use forward slashs like "C:/somedir/to/", not "C:\somedir\to\". The PREFIX is only used as a basename for supported DDNS accounts (see --provider). The saved filename is constructed like this: PREFIX---.log | See option --system A sample filename in Linux could be something like this if PREFIX were set to "/var/log/dyndns/": /var/log/dyndns/eth0-statdns-my.dyndns.org-dyndns.log -f, --file-default Use reasonable default for saved IP file PREFIX (see --file). Under Windows, %WINDIR% is used. Under Linux the PREFIXes searched are /var/log/dyndns/ (if directory exists) /var/log/ (system's standard) $HOME/tmp or $HOME If process is not running under root This options is by default activated if --file is not in use. --proxy HOST Use HOST as outgoing HTTP proxy. -P, --provider TYPE By default, program connects to "dyndns.org" to update the dynamic IP address. There are many free dynamic DNS providers are reported. Supported list of TYPES in alphabetical order: hnorg No domain name limists Basic DDNS service is free (as of 2003-10-02) http://hn.org/ dyndns No domain name limits. Basic DDNS service is free (as of 2003-10-02) http://www.dyndns.org/ See also http://members.dyndns.org/ noip No domain name limits. Basic DDNS service is free (as of 2003-10-02) http://www.no-ip.com/ NOTE: as of 2010, the support for sites of hnorg, noip is probably non-working due to changes in the interfaces. Please use only dyndns at this time. --query Query current IP address and quit. Note: if you use router, you may need --urlping* options, otherwise the IP address returned is your subnet's DHCP IP and not the ISP's Internet IP. Output of the command is at least two string. The second string is "last-ip-info-not-available" if the saved ip file name is not specified. In order to program to know where to look for saved IP files you need to give some --file* or --config option. The second string can also be "nochange" if current IP address is same as what was found from saved file. Examples: 100.197.1.6 last-ip-info-not-available 100.197.1.6 100.197.1.7 100.197.1.6 nochange 18 | How many days since last saved IP Note for tool developers: additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right. --query-ipchanged ['exitcode'] Print message if IP has changed or not. This option can take an optional string argument "exitcode" which causes program to indicate changed ip address with standard shell status code (in bash shell that would available at variable $?): $ dyndns --query-ipchange exitcode --file-default \ --provider dyndns --host xxx.dyndns.org $ echo $? ... the status code of shell ($?) would be: 0 true value, changed 1 false value, error code, i.e. not changed Without the "exitcode" argument, the returned strings are: Current IP address | changed 35 111.222.333.444 nochange 18 | Days since last IP update. Based on saved IP file's time stamp. If the last saved IP file's time stamp is too old, then even if the IP were not really changed, the situation is reported with word "changed". This is due to time limits the DDNS providers have. The account would expire unless it is updated in NN days. Note for tool developers: additional information may be provided in future. Don't rely on the count of the output words, but instead parse output from left to right. --query-ipfile Print the name of the IP file and quit. Note: In order for this option to work, you must supply all other options would be normally pass to update the DDNS account, because the Ip filename depends on these options. Alternatively provide option --config FILE from where all relevant information if read. --ethernet [optional, defaults to eth0] --provider [optional, defaults to dyndns] --system [optional, defaults to dyndns] --host required. Here is an example which supposed that directory "/var/log/dyndns/" already exists: $ dyndns --file-default --query-ipfile \ --provider dyndns --host xxx.dyndns.org /var/log/dyndns/eth0-dyndns-dyndns-xxx-dyndns.org.log --regexp REGEXP In host, which has multiple netword cards, the response can include multiple IP addresses. The default is to pick always the first choice, but that may not be what is wanted. The regexp MUST not contain capturing parentheses: if you need one, use non-capturing choice (?:). Refer to Perl manual page "perlre" for more information about non-cpaturing regular expression parentheses. Here is an example from Windows: Ethernet adapter {3C317757-AEE8-4DA7-9B68-C67B4D344103}: Connection-specific DNS Suffix . : Autoconfiguration IP Address. . . : 169.254.241.150 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . : Ethernet adapter Local Area Connection 3: Connection-specific DNS Suffix . : somewhere.net IP Address. . . . . . . . . . . . : 193.10.221.45 Subnet Mask . . . . . . . . . . . : 255.255.0.0 Default Gateway . . . . . . . . . : 10.10.0.101 The 193.10.221.45 is the intended dynamic IP address, not the first one. To instruct searching from somewhere else in the listing, supply a regular expressions that can match a portion in the listing after which the IP address appears. In the above case, the regexp could be: --regexp "Connection 3:" In Windows, the words that follow "IP Address" are automatically expected, so you should not add them to the regexp. In FreeBSD 4.5, you may get following response: tun0: flags mtu 1492 inet6 fe80::250:4ff:feef:7998%tun0 prefixlen 64 scopeid 0x7 inet 62.214.33.49 --> 255.255.255.255 netmask 0xffffffff inet 62.214.32.12 --> 255.255.255.255 netmask 0xffffffff inet 62.214.35.49 --> 255.255.255.255 netmask 0xffffffff inet 62.214.33.163 --> 62.214.32.1 netmask 0xff000000 Opened by PID 64 The correct IP address to pick from the listing is the one, which does not contain netmask 0xffffffff. The picked address for above is therefore 62.214.33.163. The regexp that finds that line is: --regexp ".*0xffffffff.*?inet" | | | Search minimum match until word "inet" search maximum match This will match all the way until the the last line with netmask 0xffffffff, after which shortest match ".*?" to "inet" is reached to read the number following it. The regexp must make sure that the next word after its match point is the wanted address. Cable, DSL and router options If you do not have direct access to world known "real" IP address, but to a subnet IP address, then you cannot determine your outside world IP address from your machine directly. See picture below: router/subnet Internet +-------------+ +-----------+ Your PC: | | maps address | | connect to ISP --> | ROUTER | -------------> | | | 192.168.... | | 80.1.1.1 | local ip says: +-------------+ +-----------+ 192.168.xxx.xxx THE REAL IP ASDL and cable modem and other connections may not be directly connected to Internet, but to a router to allow subnnetting internal hosts. This makes several computers to access the Internet while the ISP has offered only one visible IP address to you. The router makes the mapping of the local subnet IP to the world known IP address, provided by the ISP when the connection was established. You need some way to find out what is the real IP is. The simplest way is to connect to a some web page, which runs a reverse lookup service which can show the connecting IP address. Note: the following web web page does not exists. To find a service that is able to display your IP address, do a google search. Let's say, that you found a fictional service "http://www.example.com/showip" and somewhere in the web page it reads: Your IP address is: 212.111.11.10 This is what you need. To automate the lookup from web page, you need to instruct the program to connect to URL page and tell how to read the ip from page by using a regular expression. Consult Perl's manual page "perlre" if you are unfamiliar with the regular expressions. For the above fictional service, the options needed would be: --urlping "http://showip.org/?showit.pl" --urlping-regexp "address is:\s+([\d.]+)" | || | |+- Read all digits and periods | | | +- capturing parentheses | +- expect any number of whitespaces NOTE: The text to match from web page is not text/plain, but text/html, so you must look at the HTML page's sources to match the IP address correctly without the bold tags etc. --urlping URL Web page where world known IP address can be read. If you find a Web server that is running some program, which can show your IP addres, use it. The example below connects to site and calls CGI program to make show the connector's IP address. Be polite. Making calls like this too often may cause putting blocks to your site. http://www.dyndns.org/cgi-bin/check_ip.cgi Be sure to use period of 60 minutes or more with --daemon option to not increase the load in the "ping" site and cause admin's to shut down the service. --urlping-dyndns Contact http://www.dyndns.org service to obtain IP address information. This is shorthand to more general optiopn --urlping. --urlping-linksys [TYPE] Specialized router option for Linksys products. This option connects to Linksys Wireless LAN 4-point router, whose page is by default at local network address -. The world known IP address (which is provided by ISP) is parsed from that page. The product is typically connected to the cable or DSL modem. Refer to routing picture presented previously. If the default login and password has been changed, options --urlping-login and --urlping-password must be supplied For TYPE information, See . Products codes currently supported include: - BEFW11S4, Wireless Access Point Router with 4-Port Switch. Page: http://192.168.1.1/Status.htm - WRT54GL, Wireless WRT54GL Wireless-G Broadband Router. Page: http://192.168.1.1/Status_Router.asp --urlping-login LOGIN If "--urlping" web page requires authentication, supply user name for a secured web page. --urlping-password LOGIN If "--urlping" web page requires authentication, supply password for a secured web page. --urlping-regexp REGEXP After connecting to page with --urlping URL, the web page is examined for REGEXP. The regexp must catch the IP to perl match $1. Use non-capturing parenthesis to control the match as needed. For example this is incorrect: --urlping-regexp "(Address|addr:)\s+([0-9.]+)" | | $1 $2 The match MUST be in "$1", so you must use non-capturing perl paentheses for the first one: --urlping-regexp "(?:Address|addr:) +([0-9.]+)" | | non-capturing $1 If this option is not given, the default value is to find first word that matches: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) Miscellaneous options --debug [LEVEL] Turn on debug with optional positive LEVEL. Use this if you want to know details how the program initiates connection or if you experience trouble contacting DDNS provider. --help Print help --help-html Print help in HTML format. --help-man Print help page in Unix manual page format. You want to feed this output to nroff -man in order to read it. --test [LEVEL] Run in test mode, do not actually update anything. LEVEL 1 allows sending HTTP ping options and getting answers. --test-driver This is for developer only. Run internal integrity tests. --test-account This is for developer only. Uses DYNDNS test account options. All command line values that set host information or provider are ignored. Refer to client page at http://clients.dyndns.org/devel --verbose Print informational messages. --version Print version and contact information. EXAMPLES To update IP address periodically, use crontab(5) entry. The update will happen only if IP has changed since last time: 0 0-23 * * * perl /dyndns To check current IP address: dyndns --query [--urlping...] | Select correct option to do the "ping" for IP Show where the ip file is/would be stored with given connect options. The option --file-default uses OS's default directory structure. dyndns --file-default --query-ipfile --provider dyndns \ --host xxx.dyndns.org To upate account information to DDNS provider: dyndns --provider dyndns --login --password --host your.dyndns.org If your router can display a web page containing the world known IP address, you can instruct to "ping" it. Suppose that router is at address 192.168.1.1 and page that displays the world known IP is "status.html", and you have to log in to the router using username "foo" and password "bar": dyndns --urlping http://192.168.1.1/Status.html \ --urlping-login foo \ --urlping-pass bar \ If the default regexp does not find IP address from the page, supply your own match with option --urlping-regexp. In case of doubt, add option --debug 1 and examine the responses. In serious doubt, contact the maintainer (see option --version) and send the full debug output. Tip: if you run a local web server, provider "www.dyndns.org" can direct calls to it. See option "--wildcard" to enable `*.your.dyndns.org' domain delegation, like if it we accessed using `www.your.dyndns.org'. CONFIGURATION FILE Instead of supplying options at command line, they can be stored to a configuration file. For each DDNS account and different domains, a separate configuration file must be created. The configuration files are read with option --config. The syntax of the configuration file includes comments that start with (#). Anything after hash-sign is interpreted as comment. Values are set in KEY = VALUE fashion, where spaces are non-significant. Keys are not case sensitive, but values are. Below, lines marked with [default] need only be set if the default value needs to be changed. Lines marked with [noip] or [dyndns] apply to only those providers' DDNS accounts. Notice that some keys, like "host", can take multple values seprated by colons. On/Off options take values [1/0] respectively. All host name values below are fictional. # /etc/dyndns/dyndns.conf # Set to "yes" to make this configuration file excluded # from updates. disable = no # [default] ethernet = eth0 # [default] group = mygourp # Provider [noip] only. host = host1.dyndns.org, host1.dyndns.org # If you route mail. See dyndns.org documentation for details # how to set up MX records. If you know nothing about DNS/BIND # Don't even consider using this option. Misuse or broken # DNS at your end will probably terminate your 'free' dyndns contract. mxhost = mxhost.dyndns.org # Details how to get the world known IP address, in case the standard # Linux 'ifconfig' or Windows 'ipconfig' programs cannot be used. This # interests mainly Cable, DSL and router owners. NOTE: You may # not use all these options. E.g. [urlping-linksys4] is alternate # to [urlping] etc. See documentation. urlping-linksys = BEFW11S4 urlping-login = joe urlping-password = mypass urlping = fictional.showip.org urlping-regexp = (?:Address|addr:)\s+([0-9.]+) # Where IPs are stored. Directory name or Directory name with # additional file prefix. The directory part must exist. You could # say 'file = /var/log/dyndns/' but that's the default. file = default # Use OS's default location # The DDNS account details login = mylogin password = mypass provider = dyndns # [default] proxy = myproxy.myisp.net # set only if needed for HTTP calls # Hou need this option only if you have multiple ethernet cards. # After which regexp the IP number appers in ifconfig(1) listing? regexp = .*0xffffffff.*?inet # What account are you using? Select 'dyndns|statdns|custom' system = dyndns # Provider [dyndns] only # Yes, delegate all *.mydomain.dyndns.org calls wildcard = 1 # End of cnfiguration file See the details of all of these options from the corresponding command line option descriptions. E.g. option 'ethernet' in configuration file corresponds to --ethernet command line option. The normal configuration file for average user would only include few lines: # /etc/dyndns/myhost.dyndns.org.conf host = myhost.dyndns.org file = default # Use OS's default location login = mylogin password = mypassword provider = dyndns system = dyndns # or 'statdns' wildcard = 1 # Delegate *.mydomain.dyndns.org # End of cnfiguration file TODO (write Debian daemon scripts) FIXME: update-rc.d dyndns start 3 4 5 6 # Debian SUPPORT REQUESTS For new Operating System, provide all relevant commands, their options, examples and their output which answer to following questions. The items in parentheses are examples from Linux: - How is the OS detected? Send result of 'id -a', or if file/dir structure can be used to detect the system. In Lunux the existence of /boot/vmlinuz could indicate that "this is a Linux OS". - What is the command to get network information (commandlike 'ifconfig') - Where are the system configuration files stored (in directory /etc?) - Where are the log files stored (under /var/log?) To add support for routers that can be connected through HTTP protocol or with some other commands, please provide connection details and full HTTP response: wget -O -dump.html http://192.168.1.0/your-network/router/page.html TROUBLESHOOTING 1. Turn on --debug to see exact details how the program runs and what HTTP requests are sent and received. 2. Most of the <--query> options can't be used standalone. Please see documentation what additional options you need to supply with them. ENVIRONMENT TMPDIR Directory of temporary files. Defaults to system temporary dir. FILES Daemon startup file /etc/default/dyndns In Linux the syslog message files are: /etc/syslog.conf daemon.err daemon.warning /var/log/daemon.log There is no default location where program would search for configuration files. Configuration files may be found in directory "/etc/dyndns/examples". It is recommended that the examples are modified and copied one directorory up in order to use option --config /etc/dyndns/*. If program is run with Windows Activestate Perl, the log file is stored to file "C:/syslog.txt". EXIT STATUS Not defined. DEPENDENCIES Uses standard Perl modules. HTTP::Headers HTTP::Request::Common LWP::UserAgent LWP::Simple Sys::Syslog STANDARDS The *dyndns* provider's client specification is at https://www.dyndns.com/developers/specs/ BUGS AND LIMITATIONS Cygwin syslog There is no syslog daemon in Cygwin. The Cygwin POSIX emulation layer takes care about syslog requests. On NT and above systems it logs to the Windows's event manager, on Win9x and ME a file is created in the root of drive "C:". See message for more details. You can see the entries in W2K Start => Settings => Administrative Tools => Computer Management: [ System Tools / Event Viewer / Application ] Debugging errors Please use option --debug 2 and save the result. Contact maintainer if you find bugs or need new features. About providers hnorg and noip The program is primarily developed and maintained to support dyndns.org. The other providers haven't been tested since 2003. SEE ALSO syslog(3), Debian package ddclient(1) See other client software at http://clients.dyndns.org AVAILABILITY http://freecode.com/projects/perl-dyndns AUTHOR This program is free software; you can redistribute and/or modify program under the terms of GNU General Public license either version 2 of the License, or (at your option) any later version. The documentation may be distributed subject to the terms and conditions set forth in GNU General Public License v2 or later (GNU GPL); or, at your option, distributed under the terms of GNU Free Documentation License version 1.2 or later (GNU FDL). dyndns-2012.0112/examples/000077500000000000000000000000001170362450400151415ustar00rootroot00000000000000dyndns-2012.0112/examples/dyndns-dynamic.conf000066400000000000000000000006421170362450400207330ustar00rootroot00000000000000# dyndns-dynamic.conf # # Dynamic IP allocations for DDNS provider dynds.org. Please # visit their site and set up your account. # # Uncomment above lines and change their content. #host = your.dyndns.org #file = default #login = mylogin #password = mypassword #provider = dyndns #system = dyndns #wildcard = 1 # End of cnfiguration file. dyndns-2012.0112/examples/dyndns-static.conf000066400000000000000000000006411170362450400205750ustar00rootroot00000000000000# dyndns-static.conf # # Static IP allocations for DDNS provider dynds.org. Please # visit their site and set up your account. # # Uncomment above lines and change their content. #host = your.dyndns.org #file = default #login = mylogin #password = mypassword #provider = dyndns #system = statdns #wildcard = 1 # End of cnfiguration file. dyndns-2012.0112/examples/noip-dynamic.conf000066400000000000000000000005561170362450400204050ustar00rootroot00000000000000# noip-dynamic.conf # # Static IP allocations for DDNS provider www.no-ip.org. Please # visit their site and set up your account. #host = your.no-ip.info #file = default #login = mylogin #password = mypassword #provider = noip #system = dyndns #wildcard = 1 # End of cnfiguration file.