From 787b76f4a3b3e98b1ec5c857f6859bc9b5af9400 Mon Sep 17 00:00:00 2001 From: wimpunk Date: Wed, 14 Jun 2006 19:51:39 +0000 Subject: [PATCH] Created trunk and tags, moved directories to it git-svn-id: svn+ssh://svn.code.sf.net/p/ddclient/code/trunk@8 3873ddee-7413-0410-b6c4-c2c57c1ab35a --- html/ddclient.css | 299 ++ html/index.php | 809 +++++ html/sinorca-print.css | 136 + html/sinorca-screen-alt.css | 292 ++ html/sinorca-screen.css | 289 ++ svn/COPYING | 340 +++ svn/COPYRIGHT | 19 + svn/Changelog | 258 ++ svn/README | 173 ++ svn/README.cisco | 35 + svn/README.ssl | 10 + svn/ddclient | 3132 ++++++++++++++++++++ svn/sample-etc_cron.d_ddclient | 17 + svn/sample-etc_ddclient.conf | 160 + svn/sample-etc_dhclient-exit-hooks | 17 + svn/sample-etc_dhcpc_dhcpcd-eth0.exe | 20 + svn/sample-etc_ppp_ip-up.local | 40 + svn/sample-etc_rc.d_init.d_ddclient | 91 + svn/sample-etc_rc.d_init.d_ddclient.lsb | 66 + svn/sample-etc_rc.d_init.d_ddclient.redhat | 41 + 20 files changed, 6244 insertions(+) create mode 100644 html/ddclient.css create mode 100644 html/index.php create mode 100644 html/sinorca-print.css create mode 100644 html/sinorca-screen-alt.css create mode 100644 html/sinorca-screen.css create mode 100644 svn/COPYING create mode 100644 svn/COPYRIGHT create mode 100644 svn/Changelog create mode 100644 svn/README create mode 100644 svn/README.cisco create mode 100644 svn/README.ssl create mode 100755 svn/ddclient create mode 100644 svn/sample-etc_cron.d_ddclient create mode 100644 svn/sample-etc_ddclient.conf create mode 100644 svn/sample-etc_dhclient-exit-hooks create mode 100644 svn/sample-etc_dhcpc_dhcpcd-eth0.exe create mode 100644 svn/sample-etc_ppp_ip-up.local create mode 100755 svn/sample-etc_rc.d_init.d_ddclient create mode 100755 svn/sample-etc_rc.d_init.d_ddclient.lsb create mode 100755 svn/sample-etc_rc.d_init.d_ddclient.redhat diff --git a/html/ddclient.css b/html/ddclient.css new file mode 100644 index 0000000..bcd68be --- /dev/null +++ b/html/ddclient.css @@ -0,0 +1,299 @@ +/************************************* + * TITLE: Sinorca Screen Stylesheet * + * URI : sinorca/sinorca-screen.css * + * MODIF: 2003-Apr-30 19:31 +0800 * + *************************************/ + + +/* ##### Common Styles ##### */ + +body { + color: black; + background-color: rgb(153,153,153); + font-family: verdana, helvetica, arial, sans-serif; + font-size: 71%; /* Enables font size scaling in MSIE */ + margin: 0; + padding: 0; +} + +html > body { + font-size: 8.5pt; +} + +acronym, .titleTip { + border-bottom: 1px dotted rgb(153,153,153); + cursor: help; + margin: 0; + padding: 0 0 0.4px 0; +} + +.doNotDisplay { + display: none; +} + +.smallCaps { + font-size: 110%; + font-variant: small-caps; +} + + +/* ##### Header ##### */ + +.superHeader { + color: white; + background-color: rgb(100,135,220); + height: 2em; +} + +.superHeader a { + color: white; + background-color: transparent; + text-decoration: none; + font-size: 91%; + margin: 0; + padding: 0 0.5ex 0 0.25ex; +} + +.superHeader a:hover { + text-decoration: underline; +} + +.superHeader .left { + position: absolute; + left: 1.5mm; + top: 0.75ex; +} + +.superHeader .right { + position: absolute; + right: 1.5mm; + top: 0.75ex; +} + +.midHeader { + color: rgb(255,255,102); + background-color: rgb(0,0,255); +} + +.headerTitle { + font-size: 337%; + font-weight: normal; + margin: 0 0 0 4mm; + padding: 0.25ex 0; +} + +.subHeader { + color: white; + background-color: rgb(0,51,153); + margin: 0; + padding: 1ex 1ex 1ex 1.5mm; +} + +.subHeader a { + color: white; + background-color: transparent; + text-decoration: none; + font-weight: bold; + margin: 0; + padding: 0 0.75ex 0 0.5ex; +} + +.subHeader a:hover { + text-decoration: underline; +} + +.superHeader .highlight, .subHeader .highlight { + color: rgb(253,160,91); + background-color: transparent; +} + + +/* ##### Side Bar ##### */ + +#side-bar { + width: 15em; + float: left; + clear: left; + border-right: 1px solid rgb(153,153,153); +} + +#side-bar div { + border-bottom: 1px solid rgb(153,153,153); +} + +.sideBarTitle { + font-weight: bold; + margin: 0 0 0.5em 2.5mm; + padding: 1em 0 0 0; +} + +#side-bar ul { + list-style-type: none; + list-style-position: outside; + margin: 0; + padding: 0 0 1.1em 0; +} + +#side-bar li { + margin: 0; + padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE 6.0 */ +} + +#side-bar a, .thisPage { + color: rgb(51,51,204); + background-color: transparent; + text-decoration: none; + margin: 0; + padding: 0.75em 1ex 0.75em 5mm; + display: block; +} + +.thisPage { + color: black; + background-color: white; + padding-left: 4mm; + border-top: 1px solid rgb(153,153,153); + border-bottom: 1px solid rgb(153,153,153); +} + +#side-bar a:hover { + color: white; + background-color: rgb(0,0,255); + text-decoration: none; +} + +.sideBarText { + line-height: 1.5em; + margin: 0 0 1em 0; + padding: 0 1.5ex 0 2.5mm; + display: block; +} + +#side-bar .sideBarText a { + text-decoration: underline; + margin: 0; + padding: 0; + display: inline; +} + +#side-bar .sideBarText a:hover { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: none; +} + +.lighterBackground { + color: inherit; + background-color: rgb(204,204,204) +} + + +/* ##### Main Copy ##### */ + +#main-copy { + color: black; + background-color: white; + background-color: rgb(255,255,204); + + + text-align: justify; + line-height: 1.5em; + margin: 0 0 0 15em; + padding: 0.5mm 5mm 5mm 5mm; + border-left: 1px solid rgb(153,153,153); +} + +#main-copy .code { +border: 1px solid; +background: white; + padding: 0.5mm 0.5mm 0.5mm 5mm; +} + +#main-copy p { + margin: 1em 1ex 2em 1ex; + padding: 0; +} + +#main-copy a { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: underline; +} + +#main-copy a:hover { + text-decoration: none; +} + +#main-copy h1 { + color: white; + background-color: rgb(255,0,0); + + font-size: 100%; + font-weight: bold; + margin: 3em 0 0 0; + padding: 0.5ex 0 0.5ex 1ex; +} + +#main-copy .topOfPage { + color: white; + background-color: transparent; + font-size: 91%; + font-weight: bold; + text-decoration: none; + margin: 2.5ex 1ex 0 0; /* For MSIE */ + padding: 0; + float: right; +} + +#main-copy > .topOfPage { + margin: 2.75ex 1ex 0 0; /* For fully standards-compliant user agents */ +} + +dl { + margin: 1em 1ex 2em 1ex; + padding: 0; +} + +dt { + font-weight: bold; + margin: 0 0 0 0; + padding: 0; +} + +dd { + margin: 0 0 2em 2em; + padding: 0; +} + + +/* ##### Footer ##### */ + +#footer { + color: rgb(255,255,151); + background-color: rgb(0,0,255); + font-size: 91%; + margin: 0; + padding: 1em 2.5mm 2.5ex 2.5mm; + clear: both; +} + +#footer .left { + line-height: 1.45em; + float: left; + clear: left; +} + +#footer .right { + text-align: right; + line-height: 1.45em; +} + +#footer a { + color: white; + background-color: transparent; + text-decoration: underline; +} + +#footer a:hover { + text-decoration: none; +} \ No newline at end of file diff --git a/html/index.php b/html/index.php new file mode 100644 index 0000000..dc04481 --- /dev/null +++ b/html/index.php @@ -0,0 +1,809 @@ + +'. + 'the ddclient project page on sourceforge'; +$link['download'] = ''. + 'sourceforge'."\n"; +$link['developers'] = "developers for ddclient on sourceforge"; + +// pages information; should be in a database + +// main +$pages[0]['nr'] = 0; +$pages[0]['title'] = "home"; +// documentation +$pages[1]['nr'] = 1; +$pages[1]['title'] = "usage"; + +$pages[2]['nr'] = 2; +$pages[2]['title'] = "supported protocols"; + +$pages[3]['nr'] = 3; +$pages[3]['title'] = "supported routers"; + +$curpage = isset($_GET['page'])?$_GET['page']:0; +$titleextra = $pages[$curpage]['title']; +$page = $pages[$curpage]['nr']; + +// filling the page; should be in a dbase to +if ($page == 0 ) { // home page +// Introduction +$text['id'] = "intro"; +$text['title'] = "Introduction"; +$text['menu'] = "Introduction"; +$text['body'] = + "

" . + "Ddclient is a Perl client used to update dynamic DNS entries for accounts " . + "on Dynamic DNS Network Services' free DNS service. It was origanally " . + "written by Paul Burry and is now maintaned by ".$link['developers'].". " . + "It has the capability to update more than only " . + "dyndns and it can fetch your WAN-ipaddress on a few different ways. Check the " . + "configuration pages to find how to do this." . + "

\n" . + "

\n" . + "According to cudeso.be:
" . + "DDclient is a small but full featured client requiring only Perl " . + "and no additional modules. It runs under most UNIX OSes and has " . + "been tested under GNU/Linux and FreeBSD. Supported features " . + "include: operating as a daemon, manual and automatic updates, " . + "static and dynamic updates, optimized updates for multiple " . + "addresses, MX, wildcards, abuse avoidance, retrying failed " . + "updates, and sending update status to syslog and through e-mail." . + "

"; +$main[] = $text; + +// install +$text['id'] = "install"; +$text['title'] = "How to install"; +$text['menu'] = "Quick Installation"; +$text['body'] = + "

\n +Ddclient doesn't have any automatic installation procedure. Get the tar-file +from " . $link['download'] . " and untar it. Copy the perl script to your +favorit location (ex. /usr/sbin) and create a /etc/ddclient/ddclient.conf +configuration file. +

+There are a few configuration examples provided which you can copy to +/etc/ddclient/ddclient.conf and modify. More info about the configuration +can be found on the usage page +

+A typical configuration like: +

+
+#
+# /etc/ddclient/ddclient.conf
+#
+protocol=dyndns2
+use=web
+login=mylogin
+password=mypassword
+myhost.dyndns.org
+
+
+

+

+You can run ddclient as "/usr/sbin/ddclient -daemon 300 -syslog" +and put it in your startup scripts. +

\n"; +$main[] = $text; + +// help part +$text['id'] = "help"; +$text['title'] = "Documentation and help"; +$text['menu'] = "Documentation"; +$text['body'] = " +

The documentation about the configuration has been splitted in three +sections. The usage page describes the most parts +of the configuration while the supported protocols +page describes the protocol-specific options. If you want to know how +to use ddclient with your router, check the +supported routers. +

+Debugging ddclient looks pretty hard but it isn't. First try to put \n". + "as less as necessary in your configuration. Try to run \n". + "`./ddclient -daemon=0 -noquiet -debug` and check the result. \n" . + "Try to add the features you need and check it again. Once \n". + "you're happy with the result, run it as a daemon.\n" . + "

\n" . + "

\n" . + "If this doesn't work for you, \n". + "there are a few places where you can look for help. If you need \n". + "any help in configuring ddclient, you could try ddclient --help. \n". + "It should give you all the possible configuration options so.\n" . + "

\n". + "

\n" . + "If you think your configuration is correct, but ddclient doesn't \n" . + "work as you expected, you can enable debug and verbose messages \n" . + "by running ddclient -daemon=0 -debug -verbose -noquiet.\n". + "

\n". + "

\n" . + "If this doesn't help for you, maybe \n" . + "\n" . + "the help forum on sourceforge can bring some help.\n" . + "I know the manual is not very clear, you have to read the example " . + "configurations included in the tar-file or you can run " . + ""ddclient --help" to get more help. " . + "If you lucky you can find some help on #ddclient on irc.freenode.net" . + "

\n" . + "

+More info about the ddclient project can be found on " . + $link['project'] . + "

"; +$main[] = $text; + + +} else if ($page == 1) { // documentation +// usage +$text['id'] = "introduction"; +$text['title'] = "Introduction"; +$text['menu'] = "intro"; +$text['body'] = + "

\n" . + "This page describes the configuration for ddclient. If you need\n". + "anymore info about supported routers or supported protocols, check the\n" . + "other pages. Other options are described here.\n" . + "\n" . + "

Normally you don't need many arguments when starting ddclient. " . + "You can run ddclient as "/usr/sbin/ddclient -daemon 300 -syslog" \n" . + "which should be enough for most configuration. You can put all the needed\n" . + "parameters in the configuration file.\n" . + "

\n" . + "

" . + "\n" . + "\n" . + "\n" . + "\n" . + "

\n" ; +$main[] = $text; + +$text['id'] = "usage"; +$text['title'] = "Usage"; +$text['menu'] = "usage"; +$text['body'] = + "usage: ddclient [options]
\n". + "options are:
\n". + "\n". + "\n". + "\n". + "\n". + "\n". + "\n". + "\n". + "\n". + "" . + "\n" . + + "\n" . + "\n" . + + "\n" . + "\n" . + + "\n" . + "\n" . + "\n" . + "\n" . + + "\n" . + "\n" . + + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "
-daemon delay run as a daemon (default: 0).
-proxy host use 'host' as the HTTP proxy.
-server host update DNS information on 'host' (default: members.dyndns.org).
-protocol type update protocol used (default: dyndns2).
-file path load configuration information from 'path' (default: /etc/ddclient/ddclient.conf).
-cache path record address used in 'path' (default: /etc/ddclient/ddclient.cache).
-pid path record process id in 'path'.
-use which how the should IP address be obtained. (default: ip). \n" . + " More information about the possible use-arguments can be found on \n" . + " the supported routers page
-ip address set the IP address to 'address'.
-if interface obtain IP address from 'interface' (default: ppp0).
-if-skip pattern skip any IP addresses before 'pattern' in the output of ifconfig {if}.
-web provider|url obtain IP address from provider's IP checking page (default: dyndns).
-web-skip pattern skip any IP addresses before 'pattern' on the web provider|url.
-fw address|url obtain IP address from firewall at 'address'.
-fw-skip pattern skip any IP addresses before 'pattern' on the firewall address|url.
-fw-login login use 'login' when getting IP from fw.
-fw-password secret use password 'secret' when getting IP from fw.
-cmd program obtain IP address from by calling {program}.
-cmd-skip pattern skip any IP addresses before 'pattern' in the output of {cmd}.
-login user login as 'user'.
-password secret use password 'secret'.
-host host update DNS information for 'host'.
-{no}retry retry failed updates. (default: noretry).
-{no}force force an update even if the update may be unnecessary (default: noforce).
-timeout max wait at most 'max' seconds for the host to respond (default: 0).
-{no}syslog log messages to syslog (default: nosyslog).
-facility {type} log messages to syslog to facility {type} (default: daemon).
-priority {pri} log messages to syslog with priority {pri} (default: notice).
-mail address e-mail messages to {address}.
-mail-failure address e-mail messages for failed updates to {address}.
-{no}exec do {not} execute; just show what would be done (default: exec).
-{no}debug print {no} debugging information (default: nodebug).
-{no}verbose print {no} verbose information (default: noverbose).
-{no}quiet print {no} messages for unnecessary updates (default: noquiet).
-help this message (default: 0).
-{no}query print {no} ip addresses and exit.
\n" ; + +$main[] = $text; +// config +$text['id'] = "config"; +$text['title'] = "Configuring ddclient"; +$text['menu'] = "config"; +$text['body'] = + "

\n" . + "The configuration file, ddclient.conf, can be used to define the \n" . + "default behaviour and operation of ddclient. The file consists of \n" . + "sequences of global variable definitions and host definitions. \n" . + "Since version 3.6.5, ddclient.conf is located by default in \n" . + "/etc/ddclient/ddclient.conf. Another location can be forced \n" . + "by using the -file option" . + "

\n" . + "

\n" . + "Global definitions look like: \n" . + "name=value [,name=value]* \n" . + "

\n" . + "

\n" . + "Next example \n" . + "specifies that ddclient should operate as a daemon, checking the \n" . + "eth0 interface for an IP address change every 5 minutes and use the \n" . + "'dyndns2' protocol by default. \n" . + "

\n" . + "
\n" .
+  	"daemon=600                   \n" .
+  	"use=if, if=eth0              \n" .
+  	"proxy=proxy.myisp.com        \n" .
+  	"protocol=dyndns2 \n" .
+	"
\n" . + "
". + "

\n" . + "

Host definitions look like: \n" . + "[name=value [,name=value]*]* a.host.domain [,b.host.domain] [login] [password] \n" . + "

\n" . + "Next example specifies two host definitions. \n" . + "The first definition will use the hammernode1 protocol, \n" . + "my-hn-login and my-hn-password to update the ip-address of \n" . + "myhost.hn.org and my2ndhost.hn.org. \n" . + "

\n" . + "The second host definition will use the current default protocol \n" . + "('dyndns2'), my-login and my-password to update the ip-address of \n" . + "myhost.dyndns.org and my2ndhost.dyndns.org. \n" . + "

\n" . + "The order of this sequence is significant because the values of any \n" . + "global variable definitions are bound to a host definition when the \n" . + "host definition is encountered. \n" . + "

\n" . + "

\n" . + "
\n" .
+  	"protocol=hammernode1, \ \n" .
+  	"login=my-hn-login, password=my-hn-password  myhost.hn.org \n" .
+  	"login=my-login, password=my-password  myhost.dyndns.org,my2nd.dyndns.org \n" .
+	"
\n" . + "
". + "

See the sample-ddclient.conf file for further examples.

\n" ; + +$main[] = $text; + +} else if ($page == 2) { // supported sevices + $text['id'] = "intro"; + $text['title'] = "Introduction about the supported protocols"; + $text['menu'] = "Introduction"; + $text['body'] = "

". + "This is an incomplete list of the services supported by ddclient. ". + "If your favoriet dynamic dns provider isn't here, check the result " . + "ddclient --help with the most recent version of ddclient. If it's " . + "there, check the patches section on sf.net and if it's really not " . + "supported by ddclient you can try to modify ddclient yourself. " . + "

" . + "

+Since ddclient version 3.7, ddclient also supports https to update +your favorit provider. Use the ssl=yes option to use this feature. +

"; + + $main[] = $text; +// dnspark +$text['id'] = "dnspark"; +$text['title'] = "dnspark protocol"; +$text['menu'] = "dnspark"; +$text['body'] = + "

The 'dnspark' protocol is used by DNS service offered by www.dnspark.com.

\n ". + "

Configuration variables applicable to the 'easydns' protocol are:\n ". + "\n" . + "\n". + "\n". + "\n". + "\n". + "\n". + "\n". + "\n". + "\n". + "
protocol=dnspark
server=fqdn.of.service defaults to www.dnspark.com
backupmx=no|yes indicates that DNSPark should be the secondary MX " . + "for this domain or host.
mx=any.host.domain a host MX'ing for this host or domain.
mxpri=priority MX priority.
login=service-login login name and password registered with the service
password=service-password
fully.qualified.host the host registered with the service.
\n" . + +"

Example ddclient.conf file entries:

\n" . + "
\n" . + "
\n" .
+  	"## single host update\n" .
+  	"protocol=dnspark,                                         \\\n" .
+  	"login=my-dnspark.com-login,                               \\\n" .
+  	"password=my-dnspark.com-password                          \\\n" .
+  	"myhost.dnspark.com \n" .
+	"\n" .
+  	"## multiple host update with wildcard'ing mx, and backupmx\n" .
+  	"protocol=dnspark,                                         \\\n" .
+  	"login=my-dnspark.com-login,                               \\\n" .
+  	"password=my-dnspark.com-password,                         \\\n" .
+  	"mx=a.host.willing.to.mx.for.me,                           \\\n" .
+  	"mxpri=10,                                                 \\\n" .
+  	"my-toplevel-domain.com,my-other-domain.com\n" .
+	"\n" .
+  	"## multiple host update to the custom DNS service\n" .
+  	"protocol=dnspark,                                         \\\n" .
+  	"login=my-dnspark.com-login,                               \\\n" .
+  	"password=my-dnspark.com-password                          \\\n" .
+  	"my-toplevel-domain.com,my-other-domain.com\n" .
+	"
\n" . 
+	"
\n" ; + +$main[] = $text; +// dslreports +$text['id'] = "dslreports"; +$text['title'] = "dslreports"; +$text['menu'] = "dslreports"; +$text['body'] = +"

The 'dslreports1' protocol is used by a free DSL monitoring service\n" . +"offered by www.dslreports.com.

\n" . + +"

Configuration variables applicable to the 'dslreports1' protocol are:

" . +"\n" . + "" . + "" . + "" . + "" . + "" . +"
protocol=dslreports1
server=fqdn.of.service defaults to www.dslreports.com
login=service-login login name and password registered with the service
password=service-password
unique-number the host registered with the service.
\n" . + +"

Example ddclient.conf file entries:

" . + "
\n" . + "
\n" .
+  "## single host update\n" .
+  "protocol=dslreports1,                                     \\\n" .
+  "server=www.dslreports.com,                                \\\n" .
+  "login=my-dslreports-login,                                \\\n" .
+  "password=my-dslreports-password                           \\\n" .
+  "123456\n" .
+"
\n" . +"\n" . + +"

Note: DSL Reports uses a unique number as the host name. This number\n" . +"can be found on the Monitor Control web page.

\n" ; +$main[] = $text; +$text['id'] = "dyndns1"; +$text['title'] = "dyndns1"; +$text['menu'] = "dyndns1"; +$text['body'] = +"

The 'dyndns1' protocol is a deprecated protocol used by the free dynamic \n". +"DNS service offered by www.dyndns.org. The 'dyndns2' should be used to \n". +"update the www.dyndns.org service. However, other services are also \n". +"using this protocol so support is still provided by ddclient.

\n". +" \n". +"Configuration variables applicable to the 'dyndns1' protocol are: \n". +"
\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . +"
protocol=dyndns1
server=fqdn.of.service defaults to members.dyndns.org
backupmx=no|yes indicates that this host is the primary MX for the domain.
mx=any.host.domain a host MX'ing for this host definition.
wildcard=no|yes add a DNS wildcard CNAME record that points to {host}
login=service-login login name and password registered with the service
password=service-password
fully.qualified.host the host registered with the service.
\n" . + +"

Example ddclient.conf file entries:

" . + "
\n" . + "
\n" .
+  "## single host update\n" . 
+  "protocol=dyndns1,                                         \\\n" . 
+  "login=my-dyndns.org-login,                                \\\n" . 
+  "password=my-dyndns.org-password                           \\\n" . 
+  "myhost.dyndns.org \n" . 
+"\n" . 
+  "## multiple host update with wildcard'ing mx, and backupmx\n" . 
+  "protocol=dyndns1,                                         \\\n" . 
+  "login=my-dyndns.org-login,                                \\\n" . 
+  "password=my-dyndns.org-password,                          \\\n" . 
+  "mx=a.host.willing.to.mx.for.me,backupmx=yes,wildcard=yes  \\\n" . 
+  "myhost.dyndns.org,my2ndhost.dyndns.org \n" . 
+  "
\n" . + "\n" . + "

Note: you only need one of the examples

\n"; + +$main[] = $text; +// dyndns2 +$text['id'] = "dyndns2"; +$text['title'] = "dyndns2"; +$text['menu'] = "dyndns2"; +$text['body'] = +"

The 'dyndns2' protocol is a newer low-bandwidth protocol used by a\n" . +"free dynamic DNS service offered by www.dyndns.org. It supports\n" . +"features of the older 'dyndns1' in addition to others. [These will be\n" . +"supported in a future version of ddclient.]

\n" . +"\n". +"

Configuration variables applicable to the 'dyndns2' protocol are:

\n" . +"\n". + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . +"
protocol=dyndns2
server=fqdn.of.service defaults to members.dyndns.org
backupmx=no|yes indicates that this host is the primary MX for the domain.
static=no|yes indicates that this host has a static IP address.
custom=no|yes indicates that this host is a 'custom' top-level domain name.
mx=any.host.domain a host MX'ing for this host definition.
wildcard=no|yes add a DNS wildcard CNAME record that points to {host}
login=service-login login name and password registered with the service
password=service-password
fully.qualified.host the host registered with the service.
\n" . + +"

Example ddclient.conf file entries:

" . + "
\n" . + "
\n" .
+  "## single host update\n" .
+  "protocol=dyndns2,                                         \\\n" .
+  "login=my-dyndns.org-login,                                \\\n" .
+  "password=my-dyndns.org-password                           \\\n" .
+  "myhost.dyndns.org \n" .
+"\n" .
+  "## multiple host update with wildcard'ing mx, and backupmx\n" .
+  "protocol=dyndns2,                                         \\\n" .
+  "login=my-dyndns.org-login,                                \\\n" .
+  "password=my-dyndns.org-password,                          \\\n" .
+  "mx=a.host.willing.to.mx.for.me,backupmx=yes,wildcard=yes  \\\n" .
+  "myhost.dyndns.org,my2ndhost.dyndns.org \n" .
+"\n" .
+  "## multiple host update to the custom DNS service\n" .
+  "protocol=dyndns2,                                         \\\n" .
+  "login=my-dyndns.org-login,                                \\\n" .
+  "password=my-dyndns.org-password                           \\\n" .
+  "my-toplevel-domain.com,my-other-domain.com\n" .
+	"
\n" . + "
\n" . + "

Note: you only need one of the examples

\n"; + +$main[] = $text; +// easydns +$text['id'] = "easydns"; +$text['title'] = "easydns"; +$text['menu'] = "easydns"; +$text['body'] = +"

The 'easydns' protocol is used by the for fee DNS service offered \n" . +"by www.easydns.com.

\n" . + +"

Configuration variables applicable to the 'easydns' protocol are:\n". +"\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "
protocol=easydns
server=fqdn.of.service defaults to members.easydns.com
backupmx=no|yes indicates that EasyDNS should be the secondary MX for this domain or host.
mx=any.host.domain a host MX'ing for this host or domain.
wildcard=no|yes add a DNS wildcard CNAME record that points to {host}
login=service-login login name and password registered with the service
password=service-password
fully.qualified.host the host registered with the service.

\n" . + +"

Example ddclient.conf file entries:

" . + "
\n" . + "
\n" .
+  "## single host update\n" .
+  "protocol=easydns,                                         \\\n" .
+  "login=my-easydns.com-login,                               \\\n" .
+  "password=my-easydns.com-password                          \\\n" .
+  "myhost.easydns.com \n" .
+"\n" .
+  "## multiple host update with wildcard'ing mx, and backupmx\n" .
+  "protocol=easydns,                                         \\\n" .
+  "login=my-easydns.com-login,                               \\\n" .
+  "password=my-easydns.com-password,                         \\\n" .
+  "mx=a.host.willing.to.mx.for.me,                           \\\n" .
+  "backupmx=yes,                                             \\\n" .
+  "wildcard=yes                                              \\\n" .
+  "my-toplevel-domain.com,my-other-domain.com\n" .
+"\n" .
+  "## multiple host update to the custom DNS service\n" .
+  "protocol=easydns,                                         \\\n" .
+  "login=my-easydns.com-login,                               \\\n" .
+  "password=my-easydns.com-password                          \\\n" .
+  "my-toplevel-domain.com,my-other-domain.com\n" .
+  "
\n" . + "
\n" . + "

"; +$main[] = $text; +// hammernode +$text['id'] = "hammernode"; +$text['title'] = "hammernode"; +$text['menu'] = "hammernode"; +$text['body'] = +"

" . +"The 'hammernode1' protocol is the protocol used by the free dynamic \n" . +"DNS service offered by Hammernode at www.hn.org

\n" . + +"Configuration variables applicable to the 'hammernode1' protocol are:

\n" . +"\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "
protocol=hammernode1
server=fqdn.of.service defaults to members.dyndns.org
login=service-login login name and password registered with the service
password=service-password
fully.qualified.host the host registered with the service.
\n" . + +"

Example ddclient.conf file entries:

\n" . + "
\n" . + "
\n" .
+  "## single host update\n" .
+  "protocol=hammernode1,                                 \\\n" .
+  "login=my-hn.org-login,                                \\\n" .
+  "password=my-hn.org-password                           \\\n" .
+  "myhost.hn.org \n" .
+"\n" .
+  "## multiple host update\n" .
+  "protocol=hammernode1,                                 \\\n" .
+  "login=my-hn.org-login,                                \\\n" .
+  "password=my-hn.org-password,                          \\\n" .
+  "myhost.hn.org,my2ndhost.hn.org\n" .
+  "
\n" . + "
\n" . + ""; + +$main[] = $text; +// namecheap +$text['id'] = "namecheap"; +$text['title'] = "namecheap"; +$text['menu'] = "namecheap"; +$text['body'] = +"

The 'namecheap' protocol is used by DNS service offered by www.namecheap.com.

\n" . +"\n" . +"

Configuration variables applicable to the 'easydns' protocol are:

\n" . +"\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . +"
protocol=namecheap
server=fqdn.of.service defaults to dynamicdns.park-your-domain.com
login=service-login login name and password registered with the service
password=service-password
fully.qualified.host the host registered with the service.
\n" . + +"

Example ddclient.conf file entries:

". + "
\n" . + "
\n" .
+  "## single host update\n" .
+  "protocol=namecheap,                                         \\\n" .
+  "login=my-namecheap.com-login,                               \\\n" .
+  "password=my-namecheap.com-password                          \\\n" .
+  "myhost.namecheap.com \n" .
+    "
\n" . + "
\n" . + "

"; + + +$main[] = $text; +$text['id'] = "zoneedit1"; +$text['title'] = "zoneedit1"; +$text['menu'] = "zoneedit1"; +$text['body'] = +"

The 'zoneedit1' protocol is used by a DNS service offered by +www.zoneedit.com.

\n" . + +"

Configuration variables applicable to the 'zoneedit1' protocol are:

\n" . + "protocol=zoneedit1 \n" . + "server=fqdn.of.service defaults to www.zoneedit.com\n" . + "login=service-login login name and password registered with the service\n" . + "password=service-password \n" . + "your.domain.name the host registered with the service.\n" . + +"

Example ddclient.conf file entries:

\n" . + "
\n" . + "
\n" .
+  "## single host update\n" .
+  "protocol=zoneedit1,                                     \\\n" .
+  "server=www.zoneedit.com,                                \\\n" .
+  "login=my-zoneedit-login,                                \\\n" .
+  "password=my-zoneedit-password                           \\\n" .
+  "my.domain.name\n" .
+  "\n" .
+  "## multiple host update                                 \\\n" .
+  "protocol=zoneedit1,                                     \\\n" .
+  "server=www.zoneedit.com,                                \\\n" .
+  "login=my-zoneedit-login,                                \\\n" .
+  "password=my-zoneedit-password                           \\\n" .
+  "my.domain.name,my2nd.domain.com\n" .
+    "
\n" . + "
\n" . + "

"; +$main[] = $text; +} else if ($page == 3) { // supported routers + $text['id'] = "intro"; + $text['title'] = "Introduction about the -use option"; + $text['menu'] = "introduction"; + $text['body'] = + "

". + "Ddclient can get the needed IP-address on a lot of different\n". + "ways. By default, it fetches it's IP from the internet but \n". + "you can it also from a router or specify it yourself.\n". + "

\n". + "

Ddclient supports a lot of different routers. To configure ". + "your favorit router, modify your use-line in your configuration ". + "to something like -use=linksys-ver2. Don't forget to put your ". + "router password and login in the configuration.". + "

". + "

". + "If your favorit router isn't here, try to run ddclient --help. \n". + "This list is rather incomplete so there are a few more routers \n". + "supported by the most recent version of ddclient. \n". + "

"; + $main[] = $text; + + $text['id'] = "nonrouter"; + $text['title'] = "Non router option"; + $text['menu'] = "Non router"; + $text['body'] = + "" . + "\n" . + "" . + "\n" . + "" . + "" . + "
-use=web obtain IP from an IP discovery page on the web. This is the default way if none is specified
-use=if obtain IP from the -if {interface}.
-use=ip obtain IP from -ip {address}.
-use=cmd obtain IP from the -cmd {external-command}.
-use=fw obtain IP from the firewall specified by -fw {type|address}.
"; + $main[] = $text; + + $text['title'] = "Incomplete list of supported routers"; + $text['menu'] = "routers"; + $text['body'] = + "". + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "\n" . + "
-use=3com-3c886a obtain IP from 3com 3c886a 56k Lan Modem at the -fw {address}.
-use=3com-oc-remote812 obtain IP from 3com OfficeConnect Remote 812 at the -fw {address}.
-use=alcatel-stp obtain IP from Alcatel Speed Touch Pro at the -fw {address}.
-use=allnet-1298 obtain IP from Allnet 1298 at the -fw {address}.
-use=cayman-3220h obtain IP from Cayman 3220-H DSL at the -fw {address}.
-use=cisco obtain IP from Cisco FW at the -fw {address}.
-use=dlink-604 obtain IP from D-Link DI-604 at the -fw {address}.
-use=dlink-614 obtain IP from D-Link DI-614+ at the -fw {address}.
-use=e-tech obtain IP from E-tech Router at the -fw {address}.
-use=elsa-lancom-dsl10 obtain IP from ELSA LanCom DSL/10 DSL FW at the -fw {address}.
-use=elsa-lancom-dsl10-ch01 obtain IP from ELSA LanCom DSL/10 DSL FW (isdn ch01) at the -fw {address}.
-use=elsa-lancom-dsl10-ch02 obtain IP from ELSA LanCom DSL/10 DSL FW (isdn ch01) at the -fw {address}.
-use=linksys obtain IP from Linksys FW at the -fw {address}.
-use=linksys2 obtain IP from Linksys FW ver 2 at the -fw {address}.
-use=maxgate-ugate3x00 obtain IP from MaxGate UGATE-3x00 FW at the -fw {address}.
-use=netgear-rt3xx obtain IP from Netgear FW at the -fw {address}.
-use=netopia-r910 obtain IP from Netopia R910 FW at the -fw {address}.
-use=smc-barricade obtain IP from SMC Barricade FW at the -fw {address}.
-use=sohoware-nbg800 obtain IP from SOHOWare BroadGuard NBG800 at the -fw {address}.
-use=vigor-2200usb obtain IP from Vigor 2200 USB at the -fw {address}.
-use=watchguard-soho obtain IP from Watchguard SOHO FW at the -fw {address}.
-use=xsense-aero obtain IP from Xsense Aero at the -fw {address}.
". + "

Remember, if your router isn't here, check the result of ddclient --help

"; + $main[] = $text; + +} +?> + + + + + + + + + + <?php echo "$title $titleextra" ?> + + + + +
Skip to main content.
+ + + + + + + + + + + +
+^ TOP\n"); +printf("

%s

\n",$text['id'],$text['title']); +printf("%s\n",$text['body']); +} +?> +
+ + + + + + diff --git a/html/sinorca-print.css b/html/sinorca-print.css new file mode 100644 index 0000000..996a9ec --- /dev/null +++ b/html/sinorca-print.css @@ -0,0 +1,136 @@ +/************************************ + * TITLE: Sinorca Print Stylesheet * + * URI : sinorca/sinorca-print.css * + * MODIF: 2003-May-01 19:30 +0800 * + ************************************/ + + +/* ##### Common Styles ##### */ + +body { + color: black; + background-color: white; + font-family: "times new roman", times, roman, serif; + font-size: 12pt; + margin: 0; + padding: 0; +} + +acronym, .titleTip { + font-style: italic; + border-bottom: none; +} + +acronym:after, .titleTip:after { /* Prints titles after the acronyms/titletips. Doesn't work in MSIE */ + content: "(" attr(title) ")"; + font-size: 90%; + font-style: normal; + padding-left: 1ex; +} + +.doNotPrint { + display: none !important; +} + + +/* ##### Header ##### */ + +#header { + margin: 0; + padding: 0; + border-bottom: 1px solid black; +} + +.superHeader { + display: none; +} + +.headerTitle { + color: black; + background-color: transparent; + font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif; + font-size: 200%; + font-weight: normal; + text-decoration: none; + margin: 0; + padding: 0 0 0.5ex 0; +} + +.subHeader { + display: none; +} + + +/* ##### Side Bar ##### */ + +#side-bar { + display: none; +} + + +/* ##### Main Copy ##### */ + +#main-copy { + text-align: justify; + margin: 0; + padding: 0; +} + +#main-copy h1 { + font-family: "trebuchet ms", verdana, helvetica, arial, sans-serif; + font-size: 120%; + margin: 2ex 0 1ex 0; + padding: 0; +} + +#main-copy a { + color: black; + background-color: transparent; + text-decoration: none; +} + +#main-copy a:after { /* Prints the links' URIs after the links' texts. Doesn't work in MSIE */ + content: "<" attr(href) ">"; + font-size: 90%; + padding-left: 1ex; +} + +p { + margin: 0 0 2ex 0; + padding: 0; +} + +dl { + margin: 0; + padding: 0; +} + +dt { + font-weight: bold; + margin: 0; + padding: 0 0 1ex 0; +} + +dd { + margin: 0 0 2ex 1.5em; + padding: 0; +} + +.topOfPage { + display: none; +} + + +/* ##### Footer ##### */ + +#footer { + margin: 2em 0 0 0; + padding: 1ex 0 0 0; + border-top: 1px solid black; +} + +#footer a { + color: black; + background-color: transparent; + text-decoration: none; +} \ No newline at end of file diff --git a/html/sinorca-screen-alt.css b/html/sinorca-screen-alt.css new file mode 100644 index 0000000..5553665 --- /dev/null +++ b/html/sinorca-screen-alt.css @@ -0,0 +1,292 @@ +/*********************************************** + * TITLE: Sinorca Alterative Screen Stylesheet * + * URI : sinorca/sinorca-screen-alt.css * + * MODIF: 2003-May-13 18:48 +0800 * + ***********************************************/ + + +/* ##### Common Styles ##### */ + +body { + color: black; + background-color: white; + font-family: verdana, helvetica, arial, sans-serif; + font-size: 71%; /* Enables font size scaling in MSIE */ + margin: 0; + padding: 0; +} + +html > body { + font-size: 8.5pt; +} + +acronym, .titleTip { + border-bottom: 1px dotted rgb(153,153,153); + cursor: help; + margin: 0; + padding: 0 0 0.4px 0; +} + +.doNotDisplay { + display: none; +} + +.smallCaps { + font-size: 110%; + font-variant: small-caps; +} + + +/* ##### Header ##### */ + +.superHeader { + color: white; + background-color: rgb(100,135,220); + height: 2em; +} + +.superHeader a { + color: white; + background-color: transparent; + text-decoration: none; + font-size: 91%; + margin: 0; + padding: 0 0.5ex 0 0.25ex; +} + +.superHeader a:hover { + text-decoration: underline; +} + +.superHeader .left { + position: absolute; + left: 1.5mm; + top: 0.75ex; +} + +.superHeader .right { + position: absolute; + right: 1.5mm; + top: 0.75ex; +} + +.midHeader { + color: rgb(39,78,144); + background-color: rgb(140,170,230); +} + +.headerTitle { + font-size: 337%; + font-weight: normal; + margin: 0 0 0 4mm; + padding: 0.25ex 0; +} + +.subHeader { + color: white; + background-color: rgb(0,51,153); + margin: 0; + padding: 1ex 1ex 1ex 1.5mm; +} + +.subHeader a { + color: white; + background-color: transparent; + text-decoration: none; + font-weight: bold; + margin: 0; + padding: 0 0.75ex 0 0.5ex; +} + +.subHeader a:hover { + text-decoration: underline; +} + +.superHeader .highlight, .subHeader .highlight { + color: rgb(253,160,91); + background-color: transparent; +} + + +/* ##### Side Boxes ##### */ + +#side-bar { + width: 14em; + margin: 2.5em 0 0 1.25mm; + float: left; + clear: left; +} + +body > #side-bar { + margin-left: 2.5mm; /* Circumvents a rendering bug in MSIE (6.0) */ +} + +.sideBarTitle { + color: white; + background-color: rgb(100,135,220); + font-weight: bold; + margin: 0; + padding: 0.4ex 0 0.4ex 0.6ex; +} + +#side-bar ul { + list-style-type: none; + list-style-position: outside; + margin: 0; + padding: 0 0 2.25em 0; +} + +#side-bar li { + margin: 0; + padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE (6.0) */ +} + +#side-bar a, .thisPage { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: none; + font-weight: bold; + margin: 0; + padding: 1.3ex 2ex; + display: block; +} + +.thisPage { + color: black; + background-color: transparent; +} + +#side-bar a:hover { + color: white; + background-color: rgb(100,135,220); + text-decoration: none; +} + +.sideBarText { + line-height: 1.5em; + margin: 0 0 2.5em 0; + padding: 1ex 0.5ex 0 0.5ex; + display: block; +} + +.sideBarText + .sideBarText { /* Not recognised by MSIE (6.0) */ + margin-top: -1.5em; +} + +#side-bar .sideBarText a { + text-decoration: underline; + font-weight: normal; + margin: 0; + padding: 0; + display: inline; +} + +#side-bar .sideBarText a:hover { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: none; +} + + +/* ##### Main Copy ##### */ + +#main-copy { + color: black; + background-color: transparent; + text-align: justify; + line-height: 1.5em; + margin: -1em 0 0 15em; + padding: 0.5mm 5mm 5mm 5mm; +} + +#bodyText { + margin: 0 0 0 15.5em; + padding: 2mm 5mm 2mm 5mm; +} + + +#main-copy p { + margin: 1em 1ex 2em 1ex; + padding: 0; +} + +#main-copy a { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: underline; +} + +#main-copy a:hover { + text-decoration: none; +} + +#main-copy h1 { + color: rgb(0,102,204); + background-color: transparent; + font-size: 145.5%; + font-weight: bold; + margin: 2em 0 0 0; + padding: 0.5ex 0 0.5ex 0.6ex; + border-bottom: 1px solid rgb(0,102,204); +} + +#main-copy .topOfPage { + color: rgb(0,102,204); + background-color: transparent; + font-size: 91%; + font-weight: bold; + text-decoration: none; + margin: 3ex 1ex 0 0; + padding: 0; + float: right; +} + +dl { + margin: 1em 1ex 2em 1ex; + padding: 0; +} + +dt { + font-weight: bold; + margin: 0 0 0 0; + padding: 0; +} + +dd { + margin: 0 0 2em 2em; + padding: 0; +} + + +/* ##### Footer ##### */ + +#footer { + color: white; + background-color: rgb(100,135,220); + font-size: 91%; + margin: 0; + padding: 1em 2.5mm 2.5ex 2.5mm; + clear: both; +} + +#footer .left { + text-align: left; + line-height: 1.45em; + float: left; + clear: left; +} + +#footer .right { + text-align: right; + line-height: 1.45em; +} + +#footer a { + color: white; + background-color: transparent; + text-decoration: underline; +} + +#footer a:hover { + text-decoration: none; +} \ No newline at end of file diff --git a/html/sinorca-screen.css b/html/sinorca-screen.css new file mode 100644 index 0000000..cfbb56c --- /dev/null +++ b/html/sinorca-screen.css @@ -0,0 +1,289 @@ +/************************************* + * TITLE: Sinorca Screen Stylesheet * + * URI : sinorca/sinorca-screen.css * + * MODIF: 2003-Apr-30 19:31 +0800 * + *************************************/ + + +/* ##### Common Styles ##### */ + +body { + color: black; + background-color: rgb(240,240,240); + font-family: verdana, helvetica, arial, sans-serif; + font-size: 71%; /* Enables font size scaling in MSIE */ + margin: 0; + padding: 0; +} + +html > body { + font-size: 8.5pt; +} + +acronym, .titleTip { + border-bottom: 1px dotted rgb(153,153,153); + cursor: help; + margin: 0; + padding: 0 0 0.4px 0; +} + +.doNotDisplay { + display: none; +} + +.smallCaps { + font-size: 110%; + font-variant: small-caps; +} + + +/* ##### Header ##### */ + +.superHeader { + color: white; + background-color: rgb(100,135,220); + height: 2em; +} + +.superHeader a { + color: white; + background-color: transparent; + text-decoration: none; + font-size: 91%; + margin: 0; + padding: 0 0.5ex 0 0.25ex; +} + +.superHeader a:hover { + text-decoration: underline; +} + +.superHeader .left { + position: absolute; + left: 1.5mm; + top: 0.75ex; +} + +.superHeader .right { + position: absolute; + right: 1.5mm; + top: 0.75ex; +} + +.midHeader { + color: rgb(39,78,144); + background-color: rgb(140,170,230); +} + +.headerTitle { + font-size: 337%; + font-weight: normal; + margin: 0 0 0 4mm; + padding: 0.25ex 0; +} + +.subHeader { + color: white; + background-color: rgb(0,51,153); + margin: 0; + padding: 1ex 1ex 1ex 1.5mm; +} + +.subHeader a { + color: white; + background-color: transparent; + text-decoration: none; + font-weight: bold; + margin: 0; + padding: 0 0.75ex 0 0.5ex; +} + +.subHeader a:hover { + text-decoration: underline; +} + +.superHeader .highlight, .subHeader .highlight { + color: rgb(253,160,91); + background-color: transparent; +} + + +/* ##### Side Bar ##### */ + +#side-bar { + width: 15em; + float: left; + clear: left; + border-right: 1px solid rgb(153,153,153); +} + +#side-bar div { + border-bottom: 1px solid rgb(153,153,153); +} + +.sideBarTitle { + font-weight: bold; + margin: 0 0 0.5em 2.5mm; + padding: 1em 0 0 0; +} + +#side-bar ul { + list-style-type: none; + list-style-position: outside; + margin: 0; + padding: 0 0 1.1em 0; +} + +#side-bar li { + margin: 0; + padding: 0.1ex 0; /* Circumvents a rendering bug (?) in MSIE 6.0 */ +} + +#side-bar a, .thisPage { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: none; + margin: 0; + padding: 0.75em 1ex 0.75em 5mm; + display: block; +} + +.thisPage { + color: black; + background-color: white; + padding-left: 4mm; + border-top: 1px solid rgb(153,153,153); + border-bottom: 1px solid rgb(153,153,153); +} + +#side-bar a:hover { + color: white; + background-color: rgb(100,135,220); + text-decoration: none; +} + +.sideBarText { + line-height: 1.5em; + margin: 0 0 1em 0; + padding: 0 1.5ex 0 2.5mm; + display: block; +} + +#side-bar .sideBarText a { + text-decoration: underline; + margin: 0; + padding: 0; + display: inline; +} + +#side-bar .sideBarText a:hover { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: none; +} + +.lighterBackground { + color: inherit; + background-color: white; +} + + +/* ##### Main Copy ##### */ + +#main-copy { + color: black; + background-color: white; + text-align: justify; + line-height: 1.5em; + margin: 0 0 0 15em; + padding: 0.5mm 5mm 5mm 5mm; + border-left: 1px solid rgb(153,153,153); +} + +#main-copy p { + margin: 1em 1ex 2em 1ex; + padding: 0; +} + +#main-copy a { + color: rgb(0,102,204); + background-color: transparent; + text-decoration: underline; +} + +#main-copy a:hover { + text-decoration: none; +} + +#main-copy h1 { + color: white; + background-color: rgb(100,135,220); + font-size: 100%; + font-weight: bold; + margin: 3em 0 0 0; + padding: 0.5ex 0 0.5ex 1ex; +} + +#main-copy .topOfPage { + color: white; + background-color: transparent; + font-size: 91%; + font-weight: bold; + text-decoration: none; + margin: 2.5ex 1ex 0 0; /* For MSIE */ + padding: 0; + float: right; +} + +#main-copy > .topOfPage { + margin: 2.75ex 1ex 0 0; /* For fully standards-compliant user agents */ +} + +dl { + margin: 1em 1ex 2em 1ex; + padding: 0; +} + +dt { + font-weight: bold; + margin: 0 0 0 0; + padding: 0; +} + +dd { + margin: 0 0 2em 2em; + padding: 0; +} + + +/* ##### Footer ##### */ + +#footer { + color: white; + background-color: rgb(100,135,220); + font-size: 91%; + margin: 0; + padding: 1em 2.5mm 2.5ex 2.5mm; + clear: both; +} + +#footer .left { + line-height: 1.45em; + float: left; + clear: left; +} + +#footer .right { + text-align: right; + line-height: 1.45em; +} + +#footer a { + color: white; + background-color: transparent; + text-decoration: underline; +} + +#footer a:hover { + text-decoration: none; +} \ No newline at end of file diff --git a/svn/COPYING b/svn/COPYING new file mode 100644 index 0000000..60549be --- /dev/null +++ b/svn/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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) 19yy + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) 19yy 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 Library General +Public License instead of this License. diff --git a/svn/COPYRIGHT b/svn/COPYRIGHT new file mode 100644 index 0000000..57342b6 --- /dev/null +++ b/svn/COPYRIGHT @@ -0,0 +1,19 @@ +ddclient - update client for www.dyndns.org accounts + +Copyright (C) 1999 Paul Burry (paul@burry.ca) +Copyright (C) 2000 Paul Burry (paul@burry.ca) +Copyright (C) 2001 Paul Burry (paul@burry.ca) + +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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA diff --git a/svn/Changelog b/svn/Changelog new file mode 100644 index 0000000..5496364 --- /dev/null +++ b/svn/Changelog @@ -0,0 +1,258 @@ +Changelog + +cvs +- Added vi tag +- Added support for 2Wire 1701HG Gateway (see + https://sourceforge.net/forum/message.php?msg_id=3496041 submitted by hemo) +- added ssl-support by perlhaq +- updated cvs version to 3.7.0-pre +- added support for Linksys RV042, see feature requests #1501093, #1500877 +- added support for netgear-rp614, see feature request #1237039 +- added support for watchguard-edge-x, patch #1468981 +- added support for dlink-524, see patch #1314272 +- added support for rtp300 +- added support for netgear-wpn824 +- added support for linksys-wcg200, see patch #1280713 +- added support for netgear-dg834g, see patch #1176425 +- added support for netgear-wgt624, see patch #1165209 +- added support for sveasoft, see patch #1102432 +- added support for smc-barricade-7004vbr, see patch #1087989 +- added support for sitecom-dc202, see patch #1060119 +- fixed the error of stripping out '#' in the middle of password, bug #1465932 +- fixed a couple bugs in sample-etc_rc.d_init.d_ddclient and added some extra auto distro detection +- added the validation of values when reading the configuration value. +- this fixes a bug when trying to use periods/intervals in the daemon check times, bug #1209743 +- added timeout option to the IO::Socket call for timing out the initial connection, bug: #1085110 + +3.6.7 +- modified sample-etc_rc.d_init.d_ddclient.lsb (bug #1231930) +- support for ConCont Protocol (patch #1265128) submitted by seather_misery +- problem with sending mail should be solved +- corrected a few writing mistakes +- support for 'NetComm NB3' adsl modem (submitted by crazyprog) +- Added Sitelutions DynDNS, fixed minor Namecheap bug (patch #1346867) + +3.6.6 +- support for olitec-SX200 +- added sample-etc_rc.d_init.d_ddclient.lsb as a sample script for lsb-compliant systems. +- support for linksys wrt854g (thanks to Nick Triantos) +- support for linksys ver 3 +- support for Thomson (Alcatel) SpeedTouch 510 (thanks to Aldoir) +- Cosmetic fixes submitted by John Owens + +3.6.5 +- there was a bug in the linksys-ver2 +- support for postscript (thanks to Larry Hendrickson) +- Changelog out of README +- modified all documentation to use /etc/ddclient/ddclient.conf (notified by nicolasmartin in bug [1070646]) + +3.6.4 +- added support for NameCheap service (thanks to Dan Boardman) +- added support for linksys ver2 (thanks to Dan Perik) + +3.6.3 +- renamed sample-etc_dhclient-enter-hooks to sample-etc_dhclient-exit-hooks +- add support for the Allnet 1298 Router +- add -a to ifconfig to query all interfaces (for Solaris and OpenBSD) +- update the process status to reflect what is happening. +- add a To: line when sending e-mail +- add mail-failure to send mail on failures only +- try all addresses for multihomed hosts (like check.dyndns.org) +- add support for dnspark +- add sample for OrgDNS.org + +3.6.2 +- add support for Xsense Aero +- add support for Alcatel Speedtouch Pro +- do authentication when either the login or password are defined. +- fix parsing of web status pages + +- 3.6 +- add support for EasyDNS (see easydns.com) +- add warning for possible incorrect continuation lines in the .conf file. +- add if-skip with the default as was used before. +- add cmd-skip. + +- 3.5.4 +- added !active result code for DynDNS.org + +- 3.5.2 +- avoid undefined variable in get_ip + +- 3.5.1 +- fix parsing of quoted strings in .conf file +- add filename and line number to any warnings regarding files. + +- 3.5 +- allow any url to be specified for -fw {address|url} + use -fw-skip {pattern} to specify a string preceding the IP address at the URL's page +- allow any url to be specified for -web {address|url} + use -web-skip {pattern} to specify a string preceding the IP address at the URL's page +- modify -test to display any IP addresses that could be obtained from + any interfaces, builtin fw definitions, or web status pages. + +- 3.4.6 (not released) +- fix errors in -help +- allow non-FQDNs as hosts; dslreports requires this. +- handle german ifconfig output +- try to get english messages from ifconfig so other languages are handled too. +- added support for com 3c886a 56k Lan Modem + +- 3.4.5 +- handle french ifconfig output + +- 3.4.4 +- added support for obtaining the IP address from a Cisco DHCP interface. + (Thanks, Tim) + +- 3.4.2 +- update last modified time when nochg is returned from dyndns +- add example regarding fw-login and fw-password's required by some + home routers + +- 3.4.1 +- add option (-pid) to record process id in a file. This option should be + defined in the .conf file as it is done in the sample. +- add detection of SIGHUP. When this signal is received, ddclient will + wake up immediately, reload it's configuration file, and update + the IP addresses if necessary. + +- 3.4 +- ALL PEOPLE USING THIS CLIENT ARE URGED TO UPGRADE TO 3.4 or better. +- fixed several timer related bugs. +- reformatted some messages. + +- 3.3.8 +- added support for the ISDN channels on ELSA LANCOM DSL/10 router + +- 3.3.7 +- suppress repeated identical e-mail messages. + +- 3.3.6 +- added support for the ELSA LANCOM DSL/10 router +- ignore 0.0.0.0 when obtained from any FW/router. + +- 3.3.5 +- fixed sample ddclient.conf. fw-ip= should be fw= +- fixed problem getting status pages for some routers + +- 3.3.4 +- added support for the MaxGate's UGATE-3x00 routers + +- 3.3.3 +- sample* correct checks for private addresses +- add redhat specific sample-etc_rc.d_init.d_ddclient.redhat +- make daemon-mode be the default when named ddclientd +- added support for the Linksys BEF* Internet Routers + +- 3.3.2 +- (sample-etc_rc.d_init.d_ddclient) set COLUMNS to a large number so that + 'ps -aef' will not prematurely truncate the CMD. + +- 3.3 +- added rpm (thanks to Bo Forslund) +- added support for the Netgear RT3xx Internet Routers +- modified sample-etc_rc.d_init.d_ddclient to work with other Unix beside RedHat. +- avoid rewritting the ddclient.cache file unnecessarily +- fixed other minor bugs + +- 3.2.0 +- add support for DynDNS's custom domain service. +- change suggested directory to /usr/sbin + +- 3.1.0 +- clean up; fix minor bugs. +- removed -refresh +- add min-interval to avoid too frequent update attempts. +- add min-error-interval to avoid too frequent update attempts when the + service is unavailable. + +- 3.0.1 +- make all values case sensitive (ie. passwords) + +- 3.0 +- new release! +- new ddclient.conf format +- rewritten to support DynDNS's NIC2 and other dynamic DNS services +- added Hammernode (hn.org) +- added ZoneEdit (zoneedit.com) +- added DSLreports (dslreports.com) host monitoring +- added support for obtaining IP addresses from +- interfaces, +- commands, +- web, +- external commands, +- Watchguard's SOHO router +- Netopia's R910 router +- and SMC's Barracade +- added daemon mode +- added logging msgs to syslog and e-mail + +- 2.3.7 +- add -refresh to the sample scripts so default arguments are obtained from the cache +- added local-ip script for obtaining the address of an interface +- added public-ip script for obtaining the ip address as seen from a public web page + +- 2.3.6 +- fixed bug the broke enabling retrying when members.dyndns.org was down. + +- 2.3.5 +- prevent warnings from earlier versions of Perl. + +- 2.3.4 +- added sample-etc_dhclient-enter-hooks for those using the ISC DHCP client (dhclient) + +- 2.3.3 +- make sure that ddclient.conf is only readable by the owner so that no one +- else can see the password (courtesy of Steve Greenland). +-- NOTE: you will need to change the permissions on ddclient.conf to prevent +-- others from obtaining viewing your password. +-- ie. chmod go-rwx /etc/ddclient.conf + +- 2.3.2 +- make sure 'quiet' messages are printed when -verbose or -debug is enabled +- fix error messages for those people using proxies. + +- 2.3 +- fixed a problem reading in cached entries + + +- 2.2.1 +- sample-etc_ppp_ip-up.local - local ip address is $4 or $PPP_LOCAL (for debian) +- use as the line terminator (some proxies are strict about this) + +- 2.2 +- added support (-static) for updating static DNS (thanks Marc Sira) +- changed ddclient.cache format (old style is still read) +- sample-etc_ppp_ip-up.local - detect improper calling sequences +- sample-etc_ppp_ip-up.local - local ip address is $3 or $PPP_LOCAL (for debian) + +- 2.1.2 +- updated README + +- 2.1.1 +- make sure result code reflects any failures +- optionally (-quiet) omit messages for unnecessary updates +- update sample-etc_cron.d_ddclient to use -quiet + +- 2.1 +- avoid unnecessary updates by recording the last hosts updated in a + cache file (default /etc/ddclient.cache) + +- optionally (-force) force an update, even if it may be unnecessary. + + This can be used to prevent dyndns.org from deleting a host that has not + required an update for a long period of time. + +- optionally (-refresh), reissue all host updates. + + This can be used together with cron to periodically update DynDNS. + See sample-etc-cron.d-ddclient for details. + +- optionally (-retry) save failed updates for future processing. + + This feature can be used to reissue updates that may have failed due to + network connectivity problems or a DynDNS server outage + +------------------------------------------------------------------------------- +$Id$ diff --git a/svn/README b/svn/README new file mode 100644 index 0000000..f70e0c9 --- /dev/null +++ b/svn/README @@ -0,0 +1,173 @@ +=============================================================================== +DDCLIENT v3.6.7 + +ddclient is a Perl client used to update dynamic DNS entries for accounts +on many dynamic DNS services. + +IMPORTANT: The format and options used by ddclient have CHANGED. + Please examine the sample configuration file. + It is highly recommended that you take advantage of the + new daemon mode of operation. + +IMPORTANT: The installation location for the ddclient script has changed from + /root/bin/ + to + /usr/sbin/ + +=============================================================================== + +Dynamic DNS services currently supported include: + +DynDNS.org - See http://www.dyndns.org for details on obtaining a free account. +Hammernode - See http://www.hn.org for details on obtaining a free account. +Zoneedit - See http://www.zoneedit.com for details. +EasyDNS - See http://www.easydns.com for details. +NameCheap - See http://www.namecheap.com for details +ConCont - See http://www.dydns.za.net for details +DnsPark - See http://www.dnspark.com for details +DslReports - See http://www.dslreports.com for details +Sitelutions - see http://www.sitelutions.com for details + +DDclient now supports many of cable/dsl broadband routers. + +Comments, suggestions and requests: use the forums on + http://sourceforge.net/projects/ddclient/ + +The code was originally written by Paul Burry and is now hosted and maintained +through sf.net. Please check out http://ddclient.sf.net and the project page. + +------------------------------------------------------------------------------- +REQUIREMENTS: + +- one or more accounts from one of the dynamic DNS services + +- Perl 5.004 or later + (you need the IO::Socket::SSL perl library for ssl-support) + +- Linux or probably any common Unix system + +------------------------------------------------------------------------------- +INSTALLATION: + + cp ddclient /usr/sbin/ + mkdir /etc/ddclient + cp sample-etc_ddclient.conf /etc/ddclient/ddclient.conf + vi /etc/ddclient/ddclient.conf + -- and change hostnames, logins, and passwords appropriately + + ## For those using Redhat style rc files and using daemon-mode: + cp sample-etc_rc.d_init.d_ddclient /etc/rc.d/init.d/ddclient + ## enable automatic startup when booting + /sbin/chkconfig --add ddclient + ## start the first time by hand + /etc/rc.d/init.d/ddclient start + + ## If you are not using daemon-mode, configure cron and dhcp or ppp + ## as described below. + +------------------------------------------------------------------------------- +TROUBLESHOOTING: + + 1. enable debugging and verbose messages. + $ ddclient -daemon=0 -debug -verbose -noquiet + + 2. Do you need to specify a proxy? + If so, just add a + proxy=your.isp.proxy + to the ddclient.conf file. + + 3. Define the IP address of your router with fw=xxx.xxx.xxx.xxx in + /etc/ddclient/ddclient.conf and then try + $ ddclient -daemon=0 -query + to see if the router status web page can be understood. + + 4. Need support for another router/firewall? + Define the router status page yourself with: + fw=url-to-your-router's-status-page + fw-skip=any-string-preceding-your-IP-address + + ddclient does something like this to provide builtin support for + common routers. + For example, the Linksys routers could have been added with: + fw=192.168.1.1/Status.htm + fw-skip=WAN.*?IP Address + + OR + Send me the output from: + $ ddclient -geturl {fw-ip-status-url} [-login login [-password password]] + and I'll add it to the next release! + + ie. for my fw/router I used: + $ ddclient -geturl 192.168.1.254/status.htm + + 5. Some broadband routers require the use of a password when ddclient + accesses its status page to determine the router's WAN IP address. + If this is the case for your router, add + fw-login=your-router-login + fw-password=your-router-password + to the beginning of your ddclient.conf file. + Note that some routers use either 'root' or 'admin' as their login + while some others accept anything. + +------------------------------------------------------------------------------- +USING DDCLIENT WITH ppp + +If you are using a ppp connection, you can easily update your DynDNS +entry with each connection, with: + ## configure pppd to update DynDNS with each connection + cp sample-etc_ppp_ip-up.local /etc/ppp/ip-up.local + +Alternatively, you may just configure ddclient to operate as a daemon +and monitor your ppp interface. + +------------------------------------------------------------------------------- +USING DDCLIENT WITH cron + +If you have not configured ddclient to use daemon-mode, you'll need to +configure cron to force an update once a month so that the dns entry will +not become stale. + + ## configure cron to force an update twice a month + cp sample-etc_cron.d_ddclient /etc/cron.d/ddclient + vi /etc/cron.d/ddclient + +------------------------------------------------------------------------------- +USING DDCLIENT WITH dhcpcd-1.3.17 + +If you are using dhcpcd-1.3.17 or thereabouts, you can easily update +your DynDNS entry automatically every time your lease is obtained +or renewed by creating an executable file named: + /etc/dhcpc/dhcpcd-{your-interface}.exe +ie.: + cp sample-etc_dhcpc_dhcpcd-eth0.exe /etc/dhcpc/dhcpcd-{your-interface}.exe + +In my case, it is named dhcpcd-eth0.exe and contains the lines: + #!/bin/sh + PATH=/usr/sbin:/root/bin:${PATH} + logger -t dhcpcd IP address changed to $1 + ddclient -proxy fasthttp.sympatico.ca -wildcard -ip $1 | logger -t ddclient + exit 0 + +Other DHCP clients may have another method of calling out to programs +for updating DNS entries. + +Alternatively, you may just configure ddclient to operate as a daemon +and monitor your ethernet interface. + +------------------------------------------------------------------------------- +USING DDCLIENT WITH dhclient + +If you are using the ISC DHCP client (dhclient), you can update +your DynDNS entry automatically every time your lease is obtained +or renewed by creating an executable file named: + /etc/dhclient-exit-hooks +ie.: + cp sample-etc_dhclient-exit-hooks /etc/dhclient-exit-hooks + +Edit /etc/dhclient-exit-hooks to change any options required. + +Alternatively, you may just configure ddclient to operate as a daemon +and monitor your ethernet interface. + +------------------------------------------------------------------------------- +$Id$ diff --git a/svn/README.cisco b/svn/README.cisco new file mode 100644 index 0000000..2d7e337 --- /dev/null +++ b/svn/README.cisco @@ -0,0 +1,35 @@ +$Id$ +Method 1 ------------------------------------------------------ + +The following config will allow the Linux machine (10.1.1.2) to read +the IP address from the DHCP interface on the Cisco router (eth0) as +user ddclient. Since ddclient is configured with a priv level of 1 it +cannot do anything except look at the routers stats, ip addresses, +etc. This should be pretty harmless even if ddclient's password were +to be discovered. + +This has been tested with Cisco IOS 12.1(5)T5 running on a Cisco 2621 +router. + +Cisco Router Config (Assuming eth0 is DHCP interface) +----------------------------------------------------- +user ddclient password password +user ddclient priv 1 +ip http auth local +ip http access-class 99 +ip http port 1021 +ip http server +access-list 99 permit host 10.1.1.2 + +DDClient Config +--------------------------------------------------- +use=cisco, fw=10.1.1.1, if=eth0, fw-login=ddclient, fw-password=password + + +Method 2 ------------------------------------------------------ + +use=fw +fw=192.168.1.1/exec/show/interfaces/CR +fw-skip=FastEthernet0/0 +fw-login=ddclient +fw-password=xxxxxxxx diff --git a/svn/README.ssl b/svn/README.ssl new file mode 100644 index 0000000..70f9ca0 --- /dev/null +++ b/svn/README.ssl @@ -0,0 +1,10 @@ +$Id$ + +Since 3.7.0, ddclient support ssl-updates +To use ssl, put "ssl=yes" in your configuration and make sure +you have IO::Socket::SSL. + +On debian, you need libio-socket-ssl-perl to have IO::Socket::SSL + +ssl support is tested on folowing dynamic dns providers: +- dyndns.org diff --git a/svn/ddclient b/svn/ddclient new file mode 100755 index 0000000..a1996a8 --- /dev/null +++ b/svn/ddclient @@ -0,0 +1,3132 @@ +#!/usr/bin/perl -w +#!/usr/local/bin/perl -w +###################################################################### +# $Id$ +# +# DDCLIENT - a Perl client for updating DynDNS information +# +# Author: Paul Burry (paul+ddclient@burry.ca) +# ddclient-developers: see https://sourceforge.net/project/memberlist.php?group_id=116817 +###################################################################### +require 5.004; +use strict; +use Getopt::Long; +use Sys::Hostname; +use IO::Socket; + +my $version = "3.7.0-pre"; +my $programd = $0; +$programd =~ s%^.*/%%; +my $program = $programd; +$program =~ s/d$//; +my $now = time; +my $hostname = hostname(); +my $etc = ($program =~ /test/i) ? './' : '/etc/ddclient/'; +my $savedir = ($program =~ /test/i) ? 'URL/' : '/tmp/'; +my $msgs = ''; +my $last_msgs = ''; + +use vars qw($file $lineno); +local $file = ''; +local $lineno = ''; + +$ENV{'PATH'} = (exists($ENV{PATH}) ? "$ENV{PATH}:" : "") . "/sbin:/usr/sbin:/bin:/usr/bin:/etc:/usr/lib:"; + +sub T_ANY {'any'}; +sub T_STRING {'string'}; +sub T_EMAIL {'e-mail address'}; +sub T_NUMBER {'number'}; +sub T_DELAY {'time delay (ie. 1d, 1hour, 1m)'}; +sub T_LOGIN {'login'}; +sub T_PASSWD {'password'}; +sub T_BOOL {'boolean value'}; +sub T_FQDN {'fully qualified host name'}; +sub T_OFQDN {'optional fully qualified host name'}; +sub T_FILE {'file name'}; +sub T_FQDNP {'fully qualified host name and optional port number'}; +sub T_PROTO {'protocol'} +sub T_USE {'ip strategy'} +sub T_IF {'interface'} +sub T_PROG {'program name'} +sub T_IP {'ip'} +sub T_POSTS {'postscript'}; + +## strategies for obtaining an ip address. +my %builtinweb = ( + 'dyndns' => { 'url' => 'http://checkip.dyndns.org/', 'skip' => 'Current IP Address', }, + 'dnspark' => { 'url' => 'http://ipdetect.dnspark.com/', 'skip' => 'Current Address:', }, +); +my %builtinfw = ( + 'watchguard-soho' => { + 'name' => 'Watchguard SOHO FW', + 'url' => '/pubnet.htm', + 'skip' => 'NAME=IPAddress VALUE=', + }, + 'netopia-r910' => { + 'name' => 'Netopia R910 FW', + 'url' => '/WanEvtLog', + 'skip' => 'local:', + }, + 'smc-barricade' => { + 'name' => 'SMC Barricade FW', + 'url' => '/status.htm', + 'skip' => 'IP Address', + }, + 'netgear-rt3xx' => { + 'name' => 'Netgear FW', + 'url' => '/mtenSysStatus.html', + 'skip' => 'IP Address', + }, + 'elsa-lancom-dsl10' => { + 'name' => 'ELSA LanCom DSL/10 DSL FW', + 'url' => '/config/1/6/8/3/', + 'skip' => 'IP.Address', + }, + 'elsa-lancom-dsl10-ch01' => { + 'name' => 'ELSA LanCom DSL/10 DSL FW (isdn ch01)', + 'url' => '/config/1/6/8/3/', + 'skip' => 'IP.Address.*?CH01', + }, + 'elsa-lancom-dsl10-ch02' => { + 'name' => 'ELSA LanCom DSL/10 DSL FW (isdn ch01)', + 'url' => '/config/1/6/8/3/', + 'skip' => 'IP.Address.*?CH02', + }, + 'linksys' => { + 'name' => 'Linksys FW', + 'url' => '/Status.htm', + 'skip' => 'WAN.*?Address', + }, + 'linksys-ver2' => { + 'name' => 'Linksys FW version 2', + 'url' => '/RouterStatus.htm', + 'skip' => 'WAN.*?Address', + }, + 'linksys-ver3' => { + 'name' => 'Linksys FW version 3', + 'url' => '/Status_Router.htm', + 'skip' => 'WAN.*?Address', + }, + 'linksys-wrt854g' => { + 'name' => 'Linksys WRT854G FW', + 'url' => '/Status_Router.asp', + 'skip' => 'IP Address:', + }, + 'maxgate-ugate3x00' => { + 'name' => 'MaxGate UGATE-3x00 FW', + 'url' => '/Status.htm', + 'skip' => 'WAN.*?IP Address', + }, + 'netcomm-nb3' => { + 'name' => 'NetComm NB3', + 'url' => '/MainPage?id=6', + 'skip' => 'ppp-0', + }, + '3com-3c886a' => { + 'name' => '3com 3c886a 56k Lan Modem', + 'url' => '/stat3.htm', + 'skip' => 'IP address in use', + }, + 'sohoware-nbg800' => { + 'name' => 'SOHOWare BroadGuard NBG800', + 'url' => '/status.htm', + 'skip' => 'Internet IP', + }, + 'xsense-aero' => { + 'name' => 'Xsense Aero', + 'url' => '/A_SysInfo.htm', + 'skip' => 'WAN.*?IP Address', + }, + 'alcatel-stp' => { + 'name' => 'Alcatel Speed Touch Pro', + 'url' => '/cgi/router/', + 'skip' => 'Brt', + }, + 'alcatel-510' => { + 'name' => 'Alcatel Speed Touch 510', + 'url' => '/cgi/ip/', + 'skip' => 'ppp', + }, + 'allnet-1298' => { + 'name' => 'Allnet 1298', + 'url' => '/cgi/router/', + 'skip' => 'WAN', + }, + '3com-oc-remote812' => { + 'name' => '3com OfficeConnect Remote 812', + 'url' => '/callEvent', + 'skip' => '.*IP address in use', + }, + 'e-tech' => { + 'name' => 'E-tech Router', + 'url' => '/Status.htm', + 'skip' => 'Public IP Address', + }, + 'cayman-3220h' => { + 'name' => 'Cayman 3220-H DSL', + 'url' => '/shell/show+ip+interfaces', + 'skip' => '.*inet', + }, + 'vigor-2200usb' => { + 'name' => 'Vigor 2200 USB', + 'url' => '/doc/online.sht', + 'skip' => 'PPPoA', +# 'skip' => 'PPPoA ', + }, + 'dlink-614' => { + 'name' => 'D-Link DI-614+', + 'url' => '/st_devic.html', + 'skip' => 'WAN', + }, + 'dlink-604' => { + 'name' => 'D-Link DI-604', + 'url' => '/st_devic.html', + 'skip' => 'WAN.*?IP.*Address', + }, + 'olitec-SX200' => { + 'name' => 'olitec-SX200', + 'url' => '/doc/wan.htm', + 'skip' => 'st_wan_ip[0] = "', + }, + 'westell-6100' => { + 'name' => 'Westell C90-610015-06 DSL Router', + 'url' => '/advstat.htm', + 'skip' => 'IP.+?Address', + }, + '2wire' => { + 'name' => '2Wire 1701HG Gateway', + 'url' => '/xslt?PAGE=B01', + 'skip' => 'Internet Address:', + }, + 'linksys-rv042-wan1' => { + 'name' => 'Linksys RV042 Dual Homed Router WAN Port 2', + 'url' => '/home.htm', + 'skip' => 'WAN1 IP', + }, + 'linksys-rv042-wan2' => { + 'name' => 'Linksys RV042 Dual Homed Router WAN Port 2', + 'url' => '/home.htm', + 'skip' => 'WAN2 IP', + }, + 'netgear-rp614' => { + 'name' => 'Netgear RP614 FW', + 'url' => '/sysstatus.html', + 'skip' => 'IP Address', + }, + 'watchguard-edge-x' => { + 'name' => 'Watchguard Edge X FW', + 'url' => '/netstat.htm', + 'skip' => 'inet addr:', + }, + 'dlink-524' => { + 'name' => 'D-Link DI-524', + 'url' => '/st_device.html', + 'skip' => 'WAN.*?Addres', + }, + 'rtp300' => { + 'name' => 'Linksys RTP300', + 'url' => '/cgi-bin/webcm?getpage=%2Fusr%2Fwww_safe%2Fhtml%2Fstatus%2FRouter.html', + 'skip' => 'Internet.*?IP Address', + }, + 'netgear-wpn824' => { + 'name' => 'Netgear WPN824 FW', + 'url' => '/RST_status.htm', + 'skip' => 'IP Address', + }, + 'linksys-wcg200' => { + 'name' => 'Linksys WCG200 FW', + 'url' => '/RgStatus.asp', + 'skip' => 'WAN.IP.*?Address', + }, + 'netgear-dg834g' => { + 'name' => 'netgear-dg834g', + 'url' => '/setup.cgi?next_file=s_status.htm&todo=cfg_init', + 'skip' => '', + }, + 'netgear-wgt624' => { + 'name' => 'Netgear WGT624', + 'url' => '/RST_st_dhcp.htm', + 'skip' => 'IP Address', + }, + 'sveasoft' => { + 'name' => 'Sveasoft WRT54G/WRT54GS', + 'url' => '/Status_Router.asp', + 'skip' => 'var wan_ip', + }, + 'smc-barricade-7004vbr' => { + 'name' => 'SMC Barricade FW (7004VBR model config)', + 'url' => '/status_main.stm', + 'skip' => 'var wan_ip=', + }, + 'sitecom-dc202' => { + 'name' => 'Sitecom DC-202 FW', + 'url' => '/status.htm', + 'skip' => 'Internet IP Address', + }, +); +my %ip_strategies = ( + 'ip' => ": obtain IP from -ip {address}", + 'web' => ": obtain IP from an IP discovery page on the web", + 'fw' => ": obtain IP from the firewall specified by -fw {type|address}", + 'if' => ": obtain IP from the -if {interface}", + 'cmd' => ": obtain IP from the -cmd {external-command}", + 'cisco' => ": obtain IP from Cisco FW at the -fw {address}", + map { $_ => sprintf ": obtain IP from %s at the -fw {address}", $builtinfw{$_}->{'name'} } keys %builtinfw, +); +sub ip_strategies_usage { + return map { sprintf(" -use=%-22s %s.", $_, $ip_strategies{$_}) } sort keys %ip_strategies; +} + +my %web_strategies = ( + 'dyndns'=> 1, + 'dnspark'=> 1, +); + +sub setv { + return { + 'type' => shift, + 'required' => shift, + 'cache' => shift, + 'config' => shift, + 'default' => shift, + 'minimum' => shift, + }; +}; +my %variables = ( + 'global-defaults' => { + 'daemon' => setv(T_DELAY, 0, 0, 1, 0, interval('60s')), + 'file' => setv(T_FILE, 0, 0, 1, "$etc$program.conf", undef), + 'cache' => setv(T_FILE, 0, 0, 1, "$etc$program.cache", undef), + 'pid' => setv(T_FILE, 0, 0, 1, "", undef), + 'proxy' => setv(T_FQDNP, 0, 0, 1, '', undef), + 'protocol' => setv(T_PROTO, 0, 0, 1, 'dyndns2', undef), + + 'use' => setv(T_USE, 0, 0, 1, 'ip', undef), + 'ip' => setv(T_IP, 0, 0, 1, undef, undef), + 'if' => setv(T_IF, 0, 0, 1, 'ppp0', undef), + 'if-skip' => setv(T_STRING,1, 0, 1, '', undef), + 'web' => setv(T_STRING,0, 0, 1, 'dyndns', undef), + 'web-skip' => setv(T_STRING,1, 0, 1, '', undef), + 'fw' => setv(T_ANY, 0, 0, 1, '', undef), + 'fw-skip' => setv(T_STRING,1, 0, 1, '', undef), + 'fw-login' => setv(T_LOGIN, 1, 0, 1, '', undef), + 'fw-password' => setv(T_PASSWD,1, 0, 1, '', undef), + 'cmd' => setv(T_PROG, 0, 0, 1, '', undef), + 'cmd-skip' => setv(T_STRING,1, 0, 1, '', undef), + + 'timeout' => setv(T_DELAY, 0, 0, 1, 0, interval('120s')), + 'retry' => setv(T_BOOL, 0, 0, 0, 0, undef), + 'force' => setv(T_BOOL, 0, 0, 0, 0, undef), + 'ssl' => setv(T_BOOL, 0, 0, 0, 0, undef), + + 'syslog' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'facility' => setv(T_STRING,0, 0, 1, 'daemon', undef), + 'priority' => setv(T_STRING,0, 0, 1, 'notice', undef), + 'mail' => setv(T_EMAIL, 0, 0, 1, '', undef), + 'mail-failure' => setv(T_EMAIL, 0, 0, 1, '', undef), + + 'exec' => setv(T_BOOL, 0, 0, 1, 1, undef), + 'debug' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'verbose' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'quiet' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'help' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'test' => setv(T_BOOL, 0, 0, 1, 0, undef), + 'geturl' => setv(T_STRING,0, 0, 0, '', undef), + + 'postscript' => setv(T_POSTS, 0, 0, 1, '', undef), + }, + 'service-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'members.dyndns.org', undef), + 'login' => setv(T_LOGIN, 1, 0, 1, '', undef), + 'password' => setv(T_PASSWD, 1, 0, 1, '', undef), + 'host' => setv(T_STRING, 1, 1, 1, '', undef), + 'ip' => setv(T_IP, 0, 1, 0, undef, undef), + 'wtime' => setv(T_DELAY, 0, 1, 1, 0, interval('30s')), + 'mtime' => setv(T_NUMBER, 0, 1, 0, 0, undef), + 'atime' => setv(T_NUMBER, 0, 1, 0, 0, undef), + 'status' => setv(T_ANY, 0, 1, 0, '', undef), + 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('30s'), 0), + 'max-interval' => setv(T_DELAY, 0, 0, 1, interval('15d'), 0), + 'min-error-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0), + + 'warned-min-interval' => setv(T_ANY, 0, 1, 0, 0, undef), + 'warned-min-error-interval' => setv(T_ANY, 0, 1, 0, 0, undef), + }, + 'dyndns-common-defaults' => { + 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), + 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), + }, + 'dnspark-common-defaults' => { + 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), + 'mxpri' => setv(T_NUMBER, 0, 0, 1, 5, undef), + }, +); +my %services = ( + 'dyndns1' => { + 'updateable' => \&nic_dyndns2_updateable, + 'update' => \&nic_dyndns1_update, + 'examples' => \&nic_dyndns1_examples, + 'variables' => merge( + $variables{'dyndns-common-defaults'}, + $variables{'service-common-defaults'}, + ), + }, + 'dyndns2' => { + 'updateable' => \&nic_dyndns2_updateable, + 'update' => \&nic_dyndns2_update, + 'examples' => \&nic_dyndns2_examples, + 'variables' => merge( + { 'custom' => setv(T_BOOL, 0, 1, 1, 0, undef), }, +# { 'offline' => setv(T_BOOL, 0, 1, 1, 0, undef), }, + $variables{'dyndns-common-defaults'}, + $variables{'service-common-defaults'}, + ), + }, + 'concont' => { + 'updateable' => undef, + 'update' => \&nic_concont_update, + 'examples' => \&nic_concont_examples, + 'variables' => merge( + $variables{'service-common-defaults'}, + { 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), }, + { 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), }, + ), + }, + 'dslreports1' => { + 'updateable' => undef, + 'update' => \&nic_dslreports1_update, + 'examples' => \&nic_dslreports1_examples, + 'variables' => merge( + { 'host' => setv(T_NUMBER, 1, 1, 1, 0, undef) }, + $variables{'service-common-defaults'}, + ), + }, + 'hammernode1' => { + 'updateable' => undef, + 'update' => \&nic_hammernode1_update, + 'examples' => \&nic_hammernode1_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'dup.hn.org', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + $variables{'service-common-defaults'}, + ), + }, + 'zoneedit1' => { + 'updateable' => undef, + 'update' => \&nic_zoneedit1_update, + 'examples' => \&nic_zoneedit1_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'www.zoneedit.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + $variables{'service-common-defaults'}, + ), + }, + 'easydns' => { + 'updateable' => undef, + 'update' => \&nic_easydns_update, + 'examples' => \&nic_easydns_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'members.easydns.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + $variables{'service-common-defaults'}, + ), + }, + 'dnspark' => { + 'updateable' => undef, + 'update' => \&nic_dnspark_update, + 'examples' => \&nic_dnspark_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'www.dnspark.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + $variables{'dnspark-common-defaults'}, + $variables{'service-common-defaults'}, + ), + }, + 'namecheap' => { + 'updateable' => undef, + 'update' => \&nic_namecheap_update, + 'examples' => \&nic_namecheap_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'dynamicdns.park-your-domain.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')),}, + $variables{'service-common-defaults'}, + ), + }, + 'sitelutions' => { + 'updateable' => undef, + 'update' => \&nic_sitelutions_update, + 'examples' => \&nic_sitelutions_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'www.sitelutions.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, 0, interval('5m')),}, + $variables{'service-common-defaults'}, + ), + }, +); +$variables{'merged'} = merge($variables{'global-defaults'}, + $variables{'service-common-defaults'}, + $variables{'dyndns-common-defaults'}, + map { $services{$_}{'variables'} } keys %services, +); + +my @opt = ( + "usage: ${program} [options]", + "options are:", + [ "daemon", "=s", "-daemon delay : run as a daemon" ], + [ "proxy", "=s", "-proxy host : use 'host' as the HTTP proxy" ], + [ "server", "=s", "-server host : update DNS information on 'host'" ], + [ "protocol", "=s", "-protocol type : update protocol used" ], + [ "file", "=s", "-file path : load configuration information from 'path'" ], + [ "cache", "=s", "-cache path : record address used in 'path'" ], + [ "pid", "=s", "-pid path : record process id in 'path'" ], + "", + [ "use", "=s", "-use which : how the should IP address be obtained." ], + &ip_strategies_usage(), + "", + [ "ip", "=s", "-ip address : set the IP address to 'address'" ], + "", + [ "if", "=s", "-if interface : obtain IP address from 'interface'" ], + [ "if-skip", "=s", "-if-skip pattern : skip any IP addresses before 'pattern' in the output of ifconfig {if}" ], + "", + [ "web", "=s", "-web provider|url : obtain IP address from provider's IP checking page" ], + [ "web-skip", "=s", "-web-skip pattern : skip any IP addresses before 'pattern' on the web provider|url" ], + "", + [ "fw", "=s", "-fw address|url : obtain IP address from firewall at 'address'" ], + [ "fw-skip", "=s", "-fw-skip pattern : skip any IP addresses before 'pattern' on the firewall address|url" ], + [ "fw-login", "=s", "-fw-login login : use 'login' when getting IP from fw" ], + [ "fw-password", "=s", "-fw-password secret : use password 'secret' when getting IP from fw" ], + "", + [ "cmd", "=s", "-cmd program : obtain IP address from by calling {program}" ], + [ "cmd-skip", "=s", "-cmd-skip pattern : skip any IP addresses before 'pattern' in the output of {cmd}" ], + "", + [ "login", "=s", "-login user : login as 'user'" ], + [ "password", "=s", "-password secret : use password 'secret'" ], + [ "host", "=s", "-host host : update DNS information for 'host'" ], + "", + [ "options", "=s", "-options opt,opt : optional per-service arguments (see below)" ], + "", + [ "ssl", "!", "-{no}ssl : do updates over encrypted SSL connection" ], + [ "retry", "!", "-{no}retry : retry failed updates." ], + [ "force", "!", "-{no}force : force an update even if the update may be unnecessary" ], + [ "timeout", "=i", "-timeout max : wait at most 'max' seconds for the host to respond" ], + + [ "syslog", "!", "-{no}syslog : log messages to syslog" ], + [ "facility", "=s", "-facility {type} : log messages to syslog to facility {type}" ], + [ "priority", "=s", "-priority {pri} : log messages to syslog with priority {pri}" ], + [ "mail", "=s", "-mail address : e-mail messages to {address}" ], + [ "mail-failure","=s", "-mail-failure address : e-mail messages for failed updates to {address}" ], + [ "exec", "!", "-{no}exec : do {not} execute; just show what would be done" ], + [ "debug", "!", "-{no}debug : print {no} debugging information" ], + [ "verbose", "!", "-{no}verbose : print {no} verbose information" ], + [ "quiet", "!", "-{no}quiet : print {no} messages for unnecessary updates" ], + [ "help", "", "-help : this message" ], + + [ "query", "!", "-{no}query : print {no} ip addresses and exit" ], + [ "test", "!", "" ], ## hidden + [ "geturl", "=s", "" ], ## hidden + "", + nic_examples(), + "$program version $version, ", + " originally written by Paul Burry, paul+ddclient\@burry.ca", + " maintained by WimPunk" +); + +## process args +my ($opt_usage, %opt) = process_args(@opt); +my ($result, %config, %globals, %cache); +my $saved_cache = ''; +my %saved_opt = %opt; +$result = 'OK'; + +test_geturl(opt('geturl')) if opt('geturl'); + +## read config file because 'daemon' mode may be defined there. +read_config(define($opt{'file'}, default('file')), \%config, \%globals); +init_config(); +test_possible_ip() if opt('query'); + +if (!opt('daemon') && $programd =~ /d$/) { + $opt{'daemon'} = minimum('daemon'); +} +my $caught_hup = 0; +my $caught_term = 0; +$SIG{'HUP'} = sub { $caught_hup = 1; }; +$SIG{'TERM'} = sub { $caught_term = 1; }; +if (opt('daemon') && !opt('force')) { + $SIG{'CHLD'} = 'IGNORE'; + my $pid = fork; + if ($pid < 0) { + print STDERR "${program}: can not fork ($!)\n"; + exit -1; + } elsif ($pid) { + exit 0; + } + $SIG{'CHLD'} = 'DEFAULT'; + $opt{'syslog'} = 1; + open(STDOUT, ">/dev/null"); + open(STDERR, ">/dev/null"); + open(STDIN, " 0) && !$caught_hup && !$caught_term) { + my $delay = $left > 10 ? 10 : $left; + + $0 = sprintf("%s - sleeping for %s seconds", $program, $left); + $left -= sleep $delay; + } + $caught_hup = 0; + $result = 0; + + } elsif (! scalar(%config)) { + warning("no hosts to update.") unless !opt('quiet') || opt('verbose') || !$daemon; + $result = 1; + + } else { + $result = $result eq 'OK' ? 0 : 1; + } +} while ($daemon && !$result && !$caught_term); + +warning("caught SIGTERM; exiting") if $caught_term; +unlink_pid(); +sendmail(); + +exit($result); + +###################################################################### +## runpostscript +###################################################################### + +sub runpostscript { + my ($ip) = @_; + + if ( defined $globals{postscript} ) { + if ( -x $globals{postscript}) { + system ("$globals{postscript} $ip &"); + } else { + warning ("Can not execute post script: %s", $globals{postscript}); + } + } +} + +###################################################################### +## update_nics +###################################################################### +sub update_nics { + my %examined = (); + + foreach my $s (sort keys %services) { + my @hosts = (); + my $updateable = $services{$s}{'updateable'}; + my $update = $services{$s}{'update'}; + + foreach my $h (sort keys %config) { + next if $config{$h}{'protocol'} ne lc($s); + $examined{$h} = 1; + next if !nic_updateable($h, $updateable); + push @hosts, $h; + } + if (@hosts) { + $0 = sprintf("%s - updating %s", $program, join(',', @hosts)); + &$update(@hosts); + runpostscript($ip); + } + } + foreach my $h (sort keys %config) { + if (!exists $examined{$h}) { + failed("%s was not updated because protocol %s is not supported.", + $h, define($config{$h}{'protocol'}, '') + ); + } + } + write_cache(opt('cache')); +} +###################################################################### +## unlink_pid() +###################################################################### +sub unlink_pid { + if (opt('pid') && opt('daemon')) { + unlink opt('pid'); + } +} + +###################################################################### +## write_pid() +###################################################################### +sub write_pid { + my $file = opt('pid'); + + if ($file && opt('daemon')) { + local *FD; + if (! open(FD, "> $file")) { + warning("Cannot create file '%s'. ($!)", $file); + + } else { + printf FD "$$\n"; + close(FD); + } + } +} + +###################################################################### +## write_cache($file) +###################################################################### +sub write_cache { + my ($file) = @_; + + ## merge the updated host entries into the cache. + foreach my $h (keys %config) { + if (! exists $cache{$h} || $config{$h}{'update'}) { + map {$cache{$h}{$_} = $config{$h}{$_} } @{$config{$h}{'cacheable'}}; + + } else { + map {$cache{$h}{$_} = $config{$h}{$_} } qw(atime wtime status); + } + } + + ## construct the cache file. + my $cache = ""; + foreach my $h (sort keys %cache) { + my $opt = join(',', map { "$_=".define($cache{$h}{$_},'') } sort keys %{$cache{$h}}); + + $cache .= sprintf "%s%s%s\n", $opt, ($opt ? ' ' : ''), $h; + } + $file = '' if defined($saved_cache) && $cache eq $saved_cache; + + ## write the updates and other entries to the cache file. + if ($file) { + $saved_cache = undef; + local *FD; + if (! open(FD, "> $file")) { + fatal("Cannot create file '%s'. ($!)", $file); + } + printf FD "## $program-$version\n"; + printf FD "## last updated at %s (%d)\n", prettytime($now), $now; + printf FD $cache; + + close(FD); + } +} +###################################################################### +## read_cache($file) - called before reading the .conf +###################################################################### +sub read_cache { + my $file = shift; + my $config = shift; + my $globals = {}; + + %{$config} = (); + ## read the cache file ignoring anything on the command-line. + if (-e $file) { + my %saved = %opt; + %opt = (); + $saved_cache = _read_config($config, $globals, "##\\s*$program-$version\\s*", $file); + %opt = %saved; + + foreach my $h (keys %cache) { + if (exists $config{$h}) { + foreach (qw(atime mtime wtime ip status)) { + $config{$h}{$_} = $cache{$h}{$_} if exists $cache{$h}{$_}; + } + } + } + } +} +###################################################################### +## parse_assignments(string) return (rest, %variables) +## parse_assignment(string) return (name, value, rest) +###################################################################### +sub parse_assignments { + my $rest = shift; + my @args = @_; + my %variables = (); + my ($name, $value); + + while (1) { + $rest =~ s/^\s+//; + ($name, $value, $rest) = parse_assignment($rest, @args); + if (defined $name) { + $variables{$name} = $value; + } else { + last; + } + } + return ($rest, %variables); +} +sub parse_assignment { + my $rest = shift; + my $stop = @_ ? shift : '[\n\s,]'; + my ($c, $name, $value); + my ($escape, $quote) = (0, ''); + + if ($rest =~ /^\s*([a-z][a-z_-]*)=(.*)/i) { + ($name, $rest, $value) = ($1, $2, ''); + + while (length($c = substr($rest,0,1))) { + $rest = substr($rest,1); + if ($escape) { + $value .= $c; + $escape = 0; + } elsif ($c eq "\\") { + $escape = 1; + } elsif ($quote && $c eq $quote) { + $quote = '' + } elsif (!$quote && $c =~ /[\'\"]/) { + $quote = $c; + } elsif (!$quote && $c =~ /^${stop}/) { + last; + } else { + $value .= $c; + } + } + } + warning("assignment ended with an open quote") if $quote; + return ($name, $value, $rest); +} +###################################################################### +## read_config +###################################################################### +sub read_config { + my $file = shift; + my $config = shift; + my $globals = shift; + my %globals = (); + + _read_config($config, $globals, '', $file, %globals); +} +sub _read_config { + my $config = shift; + my $globals = shift; + my $stamp = shift; + local $file = shift; + my %globals = @_; + my %config = (); + my $content = ''; + + local *FD; + if (! open(FD, "< $file")) { + # fatal("Cannot open file '%s'. ($!)", $file); + warning("Cannot open file '%s'. ($!)", $file); + } + # Check for only owner has any access to config file + my ($dev, $ino, $mode, @statrest) = stat(FD); + if ($mode & 077) { + if (-f FD && (chmod 0600, $file)) { + warning("file $file must be accessible only by its owner (fixed)."); + } else { + # fatal("file $file must be accessible only by its owner."); + warning("file $file must be accessible only by its owner."); + } + } + + local $lineno = 0; + my $continuation = ''; + while () { + s/[\r\n]//g; + + $lineno++; + + ## check for the program version stamp + if (($. == 1) && $stamp && ($_ !~ /^$stamp$/i)) { + warning("program version mismatch; ignoring %s", $file); + last; + } + if (/\\\s+$/) { + warning("whitespace follows the \\ at the end-of-line.\nIf you meant to have a line continuation, remove the trailing whitespace."); + } + + $content .= "$_\n" unless /^#/; + # lines contain passwords are a special case, we don't want to + # arbitrarily strip out '#' + if (/^(\S*password\S*)\s*=\s*(\S+)/i) { $_ = "$1=$2"; } + if (/^#/ || !(/password/i) || /#.*password/i) { s/#.*//; } # remove comments + + ## handle continuation lines + $_ = "$continuation$_"; + if (/\\$/) { + chop; + $continuation = $_; + next; + } + $continuation = ''; + + s/^\s+//; # remove leading white space + s/\s+$//; # remove trailing white space + s/\s+/ /g; # canonify + next if /^$/; + + ## expected configuration line is: + ## [opt=value,opt=..] [host [login [password]]] + my %locals; + ($_, %locals) = parse_assignments($_); + s/\s*,\s*/,/g; + my @args = split; + + ## verify that keywords are valid...and check the value + foreach my $k (keys %locals) { + if (!exists $variables{'merged'}{$k}) { + warning("unrecognized keyword '%s' (ignored)", $k); + delete $locals{$k}; + } else { + my $def = $variables{'merged'}{$k}; + my $value = check_value($locals{$k}, $def); + if (!defined($value)) { + warning("Invalid Value for keyword '%s' = '%s'", $k, $locals{$k}); + delete $locals{$k}; + } else { $locals{$k} = $value; } + } + } + if (exists($locals{'host'})) { + $args[0] = @args ? "$args[0],$locals{host}" : "$locals{host}"; + } + ## accumulate globals + if ($#args < 0) { + map { $globals{$_} = $locals{$_} } keys %locals; + } + + ## process this host definition + if (@args) { + my ($host, $login, $password) = @args; + + ## add in any globals.. + %locals = %{ merge(\%locals, \%globals) }; + + ## override login and password if specified the old way. + $locals{'login'} = $login if defined $login; + $locals{'password'} = $password if defined $password; + + ## allow {host} to be a comma separated list of hosts + foreach my $h (split_by_comma($host)) { + ## save a copy of the current globals + $config{$h} = { %locals }; + $config{$h}{'host'} = $h; + } + } + } + close(FD); + + warning("file ends while expecting a continuation line.") + if $continuation; + + %$globals = %globals; + %$config = %config; + + return $content; +} +###################################################################### +## init_config - +###################################################################### +sub init_config { + %opt = %saved_opt; + + ## + $opt{'quiet'} = 0 if opt('verbose'); + + ## infer the IP strategy if possible + $opt{'use'} = 'ip' if !define($opt{'use'}) && defined($opt{'ip'}); + $opt{'use'} = 'if' if !define($opt{'use'}) && defined($opt{'if'}); + $opt{'use'} = 'web' if !define($opt{'use'}) && defined($opt{'web'}); + + ## sanity check + $opt{'max-interval'} = max(interval(opt('max-interval')), interval(default('max-interval'))); + $opt{'min-interval'} = max(interval(opt('min-interval')), interval(default('min-interval'))); + $opt{'min-error-interval'} = max(interval(opt('min-error-interval')), interval(default('min-error-interval'))); + + $opt{'timeout'} = 0 if opt('timeout') < 0; + $opt{'daemon'} = minimum('daemon') + if define($opt{'daemon'},$globals{'daemon'},0) + && define($opt{'daemon'},$globals{'daemon'}) < minimum('daemon'); + + ## define or modify host options specified on the command-line + if (exists $opt{'options'} && defined $opt{'options'}) { + ## collect cmdline configuration options. + my %options = (); + foreach my $opt (split_by_comma($opt{'options'})) { + my ($name,$var) = split /\s*=\s*/, $opt; + $options{$name} = $var; + } + ## determine hosts specified with -host + my @hosts = (); + if (exists $opt{'host'}) { + foreach my $h (split_by_comma($opt{'host'})) { + push @hosts, $h; + } + } + ## and those in -options=... + if (exists $options{'host'}) { + foreach my $h (split_by_comma($options{'host'})) { + push @hosts, $h; + } + delete $options{'host'}; + } + ## merge options into host definitions or globals + if (@hosts) { + foreach my $h (@hosts) { + $config{$h} = %{ merge(\%options, $config{$h}) }; + } + $opt{'host'} = join(',', @hosts); + } else { + %globals = %{ merge(\%options, \%globals) }; + } + } + + ## override global options with those on the command-line. + foreach my $o (keys %opt) { + if (defined $opt{$o} && exists $variables{'global-defaults'}{$o}) { + $globals{$o} = $opt{$o}; + } + } + + ## sanity check + if (defined $opt{'host'} && defined $opt{'retry'}) { + usage("options -retry and -host (or -option host=..) are mutually exclusive"); + } + + ## determine hosts to update (those on the cmd-line, config-file, or failed cached) + my @hosts = keys %config; + if (opt('host')) { + @hosts = split_by_comma($opt{'host'}); + } + if (opt('retry')) { + @hosts = map { $_ if $cache{$_}{'status'} ne 'good' } keys %cache; + } + + ## remove any other hosts + my %hosts; + map { $hosts{$_} = undef } @hosts; + map { delete $config{$_} unless exists $hosts{$_} } keys %config; + + ## collect the cacheable variables. + foreach my $proto (keys %services) { + my @cacheable = (); + foreach my $k (keys %{$services{$proto}{'variables'}}) { + push @cacheable, $k if $services{$proto}{'variables'}{$k}{'cache'}; + } + $services{$proto}{'cacheable'} = [ @cacheable ]; + } + + ## sanity check.. + ## make sure config entries have all defaults and they meet minimums + ## first the globals... + foreach my $k (keys %globals) { + my $def = $variables{'merged'}{$k}; + my $ovalue = define($globals{$k}, $def->{'default'}); + my $value = check_value($ovalue, $def); + if ($def->{'required'} && !defined $value) { + $value = default($k); + warning("'%s=%s' is an invalid %s. (using default of %s)", $k, $ovalue, $def->{'type'}, $value); + } + $globals{$k} = $value; + } + + ## now the host definitions... + HOST: + foreach my $h (keys %config) { + my $proto; + $proto = $config{$h}{'protocol'}; + $proto = opt('protocol') if !defined($proto); + + if (!exists($services{$proto})) { + warning("skipping host: %s: unrecognized protocol '%s'", $h, $proto); + delete $config{$h}; + + } else { + my $svars = $services{$proto}{'variables'}; + my $conf = { 'protocol' => $proto }; + + foreach my $k (keys %$svars) { + my $def = $svars->{$k}; + my $ovalue = define($config{$h}{$k}, $def->{'default'}); + my $value = check_value($ovalue, $def); + if ($def->{'required'} && !defined $value) { + warning("skipping host: %s: '%s=%s' is an invalid %s.", $h, $k, $ovalue, $def->{'type'}); + delete $config{$h}; + next HOST; + } + $conf->{$k} = $value; + + } + $config{$h} = $conf; + $config{$h}{'cacheable'} = [ @{$services{$proto}{'cacheable'}} ]; + } + } + if (opt('help')) { + *STDERR = *STDOUT; + usage(); + } +} + +###################################################################### +## usage +###################################################################### +sub usage { + my $msg = ''; + if (@_) { + my $format = shift; + $msg .= sprintf $format, @_; + 1 while chomp($msg); + $msg .= "\n"; + } + printf STDERR "%s%s\n", $msg, $opt_usage; + sendmail(); + exit 1; +} + +###################################################################### +## process_args - +###################################################################### +sub process_args { + my @spec = (); + my $usage = ""; + my %opts = (); + + foreach (@_) { + if (ref $_) { + my ($key, $specifier, $arg_usage) = @$_; + my $value = default($key); + + ## add a option specifier + push @spec, $key . $specifier; + + ## define the default value which can be overwritten later + $opt{$key} = undef; + + next unless $arg_usage; + + ## add a line to the usage; + $usage .= " $arg_usage"; + if (defined($value) && $value ne '') { + $usage .= " (default: "; + if ($specifier eq '!') { + $usage .= "no" if ($specifier eq '!') && !$value; + $usage .= $key; + } else { + $usage .= $value; + } + $usage .= ")"; + } + $usage .= "."; + } else { + $usage .= $_; + } + $usage .= "\n"; + } + ## process the arguments + if (! GetOptions(\%opt, @spec)) { + $opt{"help"} = 1; + } + return ($usage, %opt); +} +###################################################################### +## test_possible_ip - print possible IPs +###################################################################### +sub test_possible_ip { + local $opt{'debug'} = 0; + + printf "use=ip, ip=%s address is %s\n", opt('ip'), define(get_ip('ip'), 'NOT FOUND') + if defined opt('ip'); + + { + local $opt{'use'} = 'if'; + foreach my $if (grep {/^[a-zA-Z]/} `ifconfig -a`) { + $if =~ s/:?\s.*//is; + local $opt{'if'} = $if; + printf "use=if, if=%s address is %s\n", opt('if'), define(get_ip('if'), 'NOT FOUND'); + } + } + if (opt('fw')) { + if (opt('fw') !~ m%/%) { + foreach my $fw (sort keys %builtinfw) { + local $opt{'use'} = $fw; + printf "use=$fw address is %s\n", define(get_ip($fw), 'NOT FOUND'); + } + } + local $opt{'use'} = 'fw'; + printf "use=fw, fw=%s address is %s\n", opt('fw'), define(get_ip(opt('fw')), 'NOT FOUND') + if ! exists $builtinfw{opt('fw')}; + + } + { + local $opt{'use'} = 'web'; + foreach my $web (sort keys %builtinweb) { + local $opt{'web'} = $web; + printf "use=web, web=$web address is %s\n", define(get_ip('web'), 'NOT FOUND'); + } + printf "use=web, web=%s address is %s\n", opt('web'), define(get_ip('web'), 'NOT FOUND') + if ! exists $builtinweb{opt('web')}; + } + if (opt('cmd')) { + local $opt{'use'} = 'cmd'; + printf "use=cmd, cmd=%s address is %s\n", opt('cmd'), define(get_ip('cmd'), 'NOT FOUND'); + } + exit 0 unless opt('debug'); +} +###################################################################### +## test_geturl - print (and save if -test) result of fetching a URL +###################################################################### +sub test_geturl { + my $url = shift; + + my $reply = geturl(opt('proxy'), $url, opt('login'), opt('password')); + print "URL $url\n";; + print defined($reply) ? $reply : "\n"; + exit; +} +###################################################################### +## load_file +###################################################################### +sub load_file { + my $file = shift; + my $buffer = ''; + + if (exists($ENV{'TEST_CASE'})) { + my $try = "$file-$ENV{'TEST_CASE'}"; + $file = $try if -f $try; + } + + local *FD; + if (open(FD, "< $file")) { + read(FD, $buffer, -s FD); + close(FD); + debug("Loaded %d bytes from %s", length($buffer), $file); + } else { + debug("Load failed from %s ($!)", $file); + } + return $buffer +} +###################################################################### +## save_file +###################################################################### +sub save_file { + my ($file, $buffer, $opt) = @_; + + $file .= "-$ENV{'TEST_CASE'}" if exists $ENV{'TEST_CASE'}; + if (defined $opt) { + my $i = 0; + while (-f "$file-$i") { + if ('unique' =~ /^$opt/i) { + my $a = join('\n', grep {!/^Date:/} split /\n/, $buffer); + my $b = join('\n', grep {!/^Date:/} split /\n/, load_file("$file-$i")); + last if $a eq $b; + } + $i++; + } + $file = "$file-$i"; + } + debug("Saving to %s", $file); + local *FD; + open(FD, "> $file") or return; + print FD $buffer; + close(FD); + return $buffer; +} +###################################################################### +## print_opt +## print_globals +## print_config +## print_cache +## print_info +###################################################################### +sub _print_hash { + my ($string, $ptr) = @_; + my $value = $ptr; + + if (! defined($ptr)) { + $value = ""; + } elsif (ref $ptr eq 'HASH') { + foreach my $key (sort keys %$ptr) { + _print_hash("${string}\{$key\}", $ptr->{$key}); + } + return; + } + printf "%-36s : %s\n", $string, $value; +} +sub print_hash { + my ($string, $hash) = @_; + printf "=== %s ====\n", $string; + _print_hash($string, $hash); +} +sub print_opt { print_hash("opt", \%opt); } +sub print_globals { print_hash("globals", \%globals); } +sub print_config { print_hash("config", \%config); } +sub print_cache { print_hash("cache", \%cache); } +sub print_info { + print_opt(); + print_globals(); + print_config(); + print_cache(); +} +###################################################################### +## pipecmd - run an external command +## logger +## sendmail +###################################################################### +sub pipecmd { + my $cmd = shift; + my $stdin = join("\n", @_); + my $ok = 0; + + ## remove trailing newlines + 1 while chomp($stdin); + + ## override when debugging. + $cmd = opt('exec') ? "| $cmd" : "> /dev/null"; + + ## execute the command. + local *FD; + if (! open(FD, $cmd)) { + printf STDERR "$program: cannot execute command %s.\n", $cmd; + + } elsif ($stdin && (! print FD "$stdin\n")) { + printf STDERR "$program: failed writting to %s.\n", $cmd; + close(FD); + + } elsif (! close(FD)) { + printf STDERR "$program: failed closing %s.($@)\n", $cmd; + + } elsif (opt('exec') && $?) { + printf STDERR "$program: failed %s. ($@)\n", $cmd; + + } else { + $ok = 1; + } + return $ok; +} +sub logger { + if (opt('syslog') && opt('facility') && opt('priority')) { + my $facility = opt('facility'); + my $priority = opt('priority'); + return pipecmd("logger -p$facility.$priority -t${program}\[$$\]", @_); + } + return 1; +} +sub sendmail { + my $recipients = opt('mail'); + + if (opt('mail-failure') && ($result ne 'OK')) { + $recipients = opt('mail-failure'); + } + if ($msgs && $recipients && $msgs ne $last_msgs) { + pipecmd("sendmail -oi $recipients", + "To: $recipients", + "Subject: status report from $program\@$hostname", + "\r\n", + $msgs, + "", + "regards,", + " $program\@$hostname (version $version)" + ); + } + $last_msgs = $msgs; + $msgs = ''; +} +###################################################################### +## split_by_comma +## merge +## default +## minimum +## opt +###################################################################### +sub split_by_comma { + my $string = shift; + + return split /\s*[, ]\s*/, $string if defined $string; + return (); +} +sub merge { + my %merged = (); + foreach my $h (@_) { + foreach my $k (keys %$h) { + $merged{$k} = $h->{$k} unless exists $merged{$k}; + } + } + return \%merged; +} +sub default { + my $v = shift; + return $variables{'merged'}{$v}{'default'}; +} +sub minimum { + my $v = shift; + return $variables{'merged'}{$v}{'minimum'}; +} +sub opt { + my $v = shift; + return $opt{$v} if defined $opt{$v}; + return $globals{$v} if defined $globals{$v}; + return default($v) if defined default($v); + return undef; +} +sub min { + my $min = shift; + foreach my $arg (@_) { + $min = $arg if $arg < $min; + } + return $min; +} +sub max { + my $max = shift; + foreach my $arg (@_) { + $max = $arg if $arg > $max; + } + return $max; +} +###################################################################### +## define +###################################################################### +sub define { + foreach (@_) { + return $_ if defined $_; + } + return undef; +} +###################################################################### +## ynu +###################################################################### +sub ynu { + my ($value, $yes, $no, $undef) = @_; + + return $no if !defined($value) || !$value; + return $yes if $value eq '1'; + foreach (qw(yes true)) { + return $yes if $_ =~ /^$value/i; + } + foreach (qw(no false)) { + return $no if $_ =~ /^$value/i; + } + return $undef; +} +###################################################################### +## msg +## debug +## warning +## fatal +###################################################################### +sub _msg { + my $log = shift; + my $prefix = shift; + my $format = shift; + my $buffer = sprintf $format, @_; + chomp($buffer); + + $prefix = sprintf "%-9s ", $prefix if $prefix; + if ($file) { + $prefix .= "file $file"; + $prefix .= ", line $lineno" if $lineno; + $prefix .= ": "; + } + if ($prefix) { + $buffer = "$prefix$buffer"; + $buffer =~ s/\n/\n$prefix /g; + } + $buffer .= "\n"; + print $buffer; + + $msgs .= $buffer if $log; + logger($buffer) if $log; + +} +sub msg { _msg(0, '', @_); } +sub verbose { _msg(1, @_) if opt('verbose'); } +sub info { _msg(1, 'INFO:', @_) if opt('verbose'); } +sub debug { _msg(0, 'DEBUG:', @_) if opt('debug'); } +sub debug2 { _msg(0, 'DEBUG:', @_) if opt('debug') && opt('verbose');} +sub warning { _msg(1, 'WARNING:', @_); } +sub fatal { _msg(1, 'FATAL:', @_); sendmail(); exit(1); } +sub success { _msg(1, 'SUCCESS:', @_); } +sub failed { _msg(1, 'FAILED:', @_); $result = 'FAILED'; } +sub prettytime { return scalar(localtime(shift)); } + +sub prettyinterval { + my $interval = shift; + use integer; + my $s = $interval % 60; $interval /= 60; + my $m = $interval % 60; $interval /= 60; + my $h = $interval % 24; $interval /= 24; + my $d = $interval; + + my $string = ""; + $string .= "$d day" if $d; + $string .= "s" if $d > 1; + $string .= ", " if $string && $h; + $string .= "$h hour" if $h; + $string .= "s" if $h > 1; + $string .= ", " if $string && $m; + $string .= "$m minute" if $m; + $string .= "s" if $m > 1; + $string .= ", " if $string && $s; + $string .= "$s second" if $s; + $string .= "s" if $s > 1; + return $string; +} +sub interval { + my $value = shift; + if ($value =~ /^(\d+)(seconds|s)/i) { + $value = $1; + } elsif ($value =~ /^(\d+)(minutes|m)/i) { + $value = $1 * 60; + } elsif ($value =~ /^(\d+)(hours|h)/i) { + $value = $1 * 60*60; + } elsif ($value =~ /^(\d+)(days|d)/i) { + $value = $1 * 60*60*24; + } elsif ($value !~ /^\d+$/) { + $value = undef; + } + return $value; +} +sub interval_expired { + my ($host, $time, $interval) = @_; + + return 1 if !exists $cache{$host}; + return 1 if !exists $cache{$host}{$time} || !$cache{$host}{$time}; + return 1 if !exists $config{$host}{$interval} || !$config{$host}{$interval}; + + return $now > ($cache{$host}{$time} + $config{$host}{$interval}); +} + + + +###################################################################### +## check_value +###################################################################### +sub check_value { + my ($value, $def) = @_; + my $type = $def->{'type'}; + my $min = $def->{'minimum'}; + my $required = $def->{'required'}; + + if (!defined $value && !$required) { + ; + + } elsif ($type eq T_DELAY) { + $value = interval($value); + $value = $min if defined($value) && defined($min) && $value < $min; + + } elsif ($type eq T_NUMBER) { + return undef if $value !~ /^\d+$/; + $value = $min if defined($min) && $value < $min; + + } elsif ($type eq T_BOOL) { + if ($value =~ /^y(es)?$|^t(true)?$|^1$/i) { + $value = 1; + } elsif ($value =~ /^n(o)?$|^f(alse)?$|^0$/i) { + $value = 0; + } else { + return undef; + } + } elsif ($type eq T_FQDN || $type eq T_OFQDN && $value ne '') { + $value = lc $value; + return undef if $value !~ /[^.]\.[^.]/; + + } elsif ($type eq T_FQDNP) { + $value = lc $value; + return undef if $value !~ /[^.]\.[^.].*(:\d+)?$/; + + } elsif ($type eq T_PROTO) { + $value = lc $value; + return undef if ! exists $services{$value}; + + } elsif ($type eq T_USE) { + $value = lc $value; + return undef if ! exists $ip_strategies{$value}; + + } elsif ($type eq T_FILE) { + return undef if $value eq ""; + + } elsif ($type eq T_IF) { + return undef if $value !~ /^[a-z0-9:_-]+$/; + + } elsif ($type eq T_PROG) { + return undef if $value eq ""; + + } elsif ($type eq T_LOGIN) { + return undef if $value eq ""; + +# } elsif ($type eq T_PASSWD) { +# return undef if $value =~ /:/; + + } elsif ($type eq T_IP) { + return undef if $value !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; + } + return $value; +} +###################################################################### +## encode_base64 - from MIME::Base64 +###################################################################### +sub encode_base64 ($;$) { + my $res = ''; + my $eol = $_[1]; + $eol = "\n" unless defined $eol; + pos($_[0]) = 0; # ensure start at the beginning + while ($_[0] =~ /(.{1,45})/gs) { + $res .= substr(pack('u', $1), 1); + chop($res); + } + $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs + + # fix padding at the end + my $padding = (3 - length($_[0]) % 3) % 3; + $res =~ s/.{$padding}$/'=' x $padding/e if $padding; + + # break encoded string into lines of no more than 76 characters each + if (length $eol) { + $res =~ s/(.{1,76})/$1$eol/g; + } + $res; +} +###################################################################### +## geturl +###################################################################### +sub geturl { + my $proxy = shift || ''; + my $url = shift || ''; + my $login = shift || ''; + my $password = shift || ''; + my ($peer, $server, $port, $default_port, $use_ssl); + my ($sd, $rq, $request, $reply); + + debug("proxy = $proxy"); + debug("url = $url"); + ## canonify proxy and url + $proxy =~ s%^https?://%%i; + $url =~ s%^https?://%%i; + $server = $url; + $server =~ s%/.*%%; + $url = "/" unless $url =~ m%/%; + $url =~ s%^[^/]*/%%; + + debug("server = $server"); + debug("opt(fw = ",opt('fw')); + debug("glo fw = $globals{'fw'}"); + #if ( $globals{'ssl'} and $server ne $globals{'fw'} ) { + ## always omit SSL for connections to local router + if ( $globals{'ssl'} and (caller(1))[3] ne 'main::get_ip' ) { + $use_ssl = 1; + $default_port = 443; + require IO::Socket::SSL; + import IO::Socket::SSL; + { no warnings; $IO::Socket::SSL::DEBUG = 0; } + } else { + $use_ssl = 0; + $default_port = 80; + } + + ## determine peer and port to use. + $peer = $proxy || $server; + $peer =~ s%/.*%%; + $port = $peer; + $port =~ s%^.*:%%; + $port = $default_port unless $port =~ /^\d+$/; + $peer =~ s%:.*$%%; + + my $to = sprintf "%s%s", $server, $proxy ? " via proxy $peer:$port" : ""; + verbose("CONNECT:", "%s", $to); + + $request = "GET "; + $request .= "http://$server" if $proxy; + $request .= "/$url HTTP/1.0\n"; + $request .= "Host: $server\n"; + + my $auth = encode_base64("${login}:${password}"); + $request .= "Authorization: Basic $auth" if $login || $password; + $request .= "User-Agent: ${program}/${version}\n"; + $request .= "Connection: close\n"; + $request .= "\n"; + + ## make sure newlines are for some pedantic proxy servers + ($rq = $request) =~ s/\n/\r\n/g; + + # local $^W = 0; + $0 = sprintf("%s - connecting to %s port %s", $program, $peer, $port); + if (! opt('exec')) { + debug("skipped network connection"); + verbose("SENDING:", $request); + } elsif ($use_ssl) { + $sd = IO::Socket::SSL->new( + PeerAddr => $peer, + PeerPort => $port, + Proto => 'tcp', + MultiHomed => 1, + Timeout => opt('timeout'), + ); + defined $sd or warning("cannot connect to $peer:$port socket: $@ " . IO::Socket::SSL::errstr()); + } else { + $sd = IO::Socket::INET->new( + PeerAddr => $peer, + PeerPort => $port, + Proto => 'tcp', + MultiHomed => 1, + Timeout => opt('timeout'), + ); + defined $sd or warning("cannot connect to $peer:$port socket: $@"); + } + + if (defined $sd) { + ## send the request to the http server + verbose("CONNECTED: ", $use_ssl ? 'using SSL' : 'using HTTP'); + verbose("SENDING:", $request); + + $0 = sprintf("%s - sending to %s port %s", $program, $peer, $port); + my $result = syswrite $sd, $rq; + if ($result != length($rq)) { + warning("cannot send to $peer:$port ($!)."); + + } else { + my $timeout = 0; + local $SIG{'ALRM'} = sub { $timeout = 1; }; + + $0 = sprintf("%s - reading from %s port %s", $program, $peer, $port); + alarm(opt('timeout')) if opt('timeout') > 0; + while (!$timeout && ($_ = <$sd>)) { + $0 = sprintf("%s - read from %s port %s", $program, $peer, $port); + verbose("RECEIVE:", "%s", define($_, "")); + $reply .= $_ if defined $_; + } + if (opt('timeout') > 0) { + alarm(0); + } + close($sd); + if ($timeout) { + warning("TIMEOUT: %s after %s seconds", $to, opt('timeout')); + $reply = ''; + } + $reply = '' if !defined $reply; + } + } + $0 = sprintf("%s - closed %s port %s", $program, $peer, $port); + + ## during testing simulate reading the URL + if (opt('test')) { + my $filename = "$server/$url"; + $filename =~ s|/|%2F|g; + if (opt('exec')) { + $reply = save_file("${savedir}$filename", $reply, 'unique'); + } else { + $reply = load_file("${savedir}$filename"); + } + } + + $reply =~ s/\r//g if defined $reply; + return $reply; +} +###################################################################### +## get_ip +###################################################################### +sub get_ip { + my $use = lc shift; + my ($ip, $arg, $reply, $url, $skip) = (undef, opt($use), ''); + $arg = '' unless $arg; + + if ($use eq 'ip') { + $ip = opt('ip'); + $arg = 'ip'; + + } elsif ($use eq 'if') { + $skip = opt('if-skip') || ''; + $reply = `ifconfig $arg 2> /dev/null`; + $reply = '' if $?; + + } elsif ($use eq 'cmd') { + if ($arg) { + $skip = opt('cmd-skip') || ''; + $reply = `$arg`; + $reply = '' if $?; + } + + } elsif ($use eq 'web') { + $url = opt('web') || ''; + $skip = opt('web-skip') || ''; + + if (exists $builtinweb{$url}) { + $skip = $builtinweb{$url}->{'skip'} unless $skip; + $url = $builtinweb{$url}->{'url'}; + } + $arg = $url; + + if ($url) { + $reply = geturl(opt('proxy'), $url) || ''; + } + + } elsif (($use eq 'cisco')) { + # Stuff added to support Cisco router ip http daemon + # User fw-login should only have level 1 access to prevent + # password theft. This is pretty harmless. + my $queryif = opt('if'); + $skip = opt('fw-skip') || ''; + + # Convert slashes to protected value "\/" + $queryif =~ s%\/%\\\/%g; + + # Protect special HTML characters (like '?') + $queryif =~ s/([\?&= ])/sprintf("%%%02x",ord($1))/ge; + + $url = "http://${arg}/level/1/exec/show/ip/interface/brief/${queryif}/CR"; + $reply = geturl('', $url, opt('fw-login'), opt('fw-password')) || ''; + $arg = $url; + + } else { + $url = opt('fw') || ''; + $skip = opt('fw-skip') || ''; + + if (exists $builtinfw{$use}) { + $skip = $builtinfw{$use}->{'skip'} unless $skip; + $url = "http://${url}" . $builtinfw{$use}->{'url'} unless $url =~ /\//; + } + $arg = $url; + + if ($url) { + $reply = geturl('', $url, opt('fw-login'), opt('fw-password')) || ''; + } + } + if (!defined $reply) { + $reply = ''; + } + if ($skip) { + $skip =~ s/ /\\s/is; + $reply =~ s/^.*?${skip}//is; + } + if ($reply =~ /^.*?\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b.*/is) { + $ip = $1; + } + if (($use ne 'ip') && (define($ip,'') eq '0.0.0.0')) { + $ip = undef; + } + + debug("get_ip: using %s, %s reports %s", $use, $arg, define($ip, "")); + return $ip; +} + +###################################################################### +## group_hosts_by +###################################################################### +sub group_hosts_by { + my ($hosts, $attributes) = @_; + + my %groups = (); + foreach my $h (@$hosts) { + my @keys = @$attributes; + map { $config{$h}{$_} = '' unless exists $config{$h}{$_} } @keys; + my $sig = join(',', map { "$_=$config{$h}{$_}" } @keys); + + push @{$groups{$sig}}, $h; + } + return %groups; +} +###################################################################### +## nic_examples +###################################################################### +sub nic_examples { + my $examples = ""; + my $separator = ""; + foreach my $s (sort keys %services) { + my $subr = $services{$s}{'examples'}; + my $example; + + if (defined($subr) && ($example = &$subr())) { + chomp($example); + $examples .= $example; + $examples .= "\n\n$separator"; + $separator = "\n"; + } + } + my $intro = < $now) { + warning("cannot update %s from %s to %s until after %s.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), $ip, + prettytime($cache{$host}{'wtime'}) + ); + + } elsif ($cache{$host}{'mtime'} && interval_expired($host, 'mtime', 'max-interval')) { + warning("forcing update of %s from %s to %s; %s since last update on %s.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), $ip, + prettyinterval($config{$host}{'max-interval'}), + prettytime($cache{$host}{'mtime'}) + ); + $update = 1; + + } elsif ($cache{$host}{'ip'} ne $ip) { + if (($cache{$host}{'status'} eq 'good') && !interval_expired($host, 'mtime', 'min-interval')) { + + warning("skipping update of %s from %s to %s.\nlast updated %s.\nWait at least %s between update attempts.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), + $ip, + ($cache{$host}{'mtime'} ? prettytime($cache{$host}{'mtime'}) : ''), + prettyinterval($config{$host}{'min-interval'}) + ) + if opt('verbose') || !define($cache{$host}{'warned-min-interval'}, 0); + + $cache{$host}{'warned-min-interval'} = $now; + + } elsif (($cache{$host}{'status'} ne 'good') && !interval_expired($host, 'atime', 'min-error-interval')) { + + warning("skipping update of %s from %s to %s.\nlast updated %s but last attempt on %s failed.\nWait at least %s between update attempts.", + $host, + ($cache{$host}{'ip'} ? $cache{$host}{'ip'} : ''), + $ip, + ($cache{$host}{'mtime'} ? prettytime($cache{$host}{'mtime'}) : ''), + ($cache{$host}{'atime'} ? prettytime($cache{$host}{'atime'}) : ''), + prettyinterval($config{$host}{'min-error-interval'}) + ) + if opt('verbose') || !define($cache{$host}{'warned-min-error-interval'}, 0); + + $cache{$host}{'warned-min-error-interval'} = $now; + + } else { + $update = 1; + } + + } elsif (defined($sub) && &$sub($host)) { + $update = 1; + + } else { + success("%s: skipped: IP address was already set to %s.", $host, $ip) + if opt('verbose'); + } + $config{$host}{'status'} = define($cache{$host}{'status'},''); + $config{$host}{'update'} = $update; + if ($update) { + $config{$host}{'status'} = 'noconnect'; + $config{$host}{'atime'} = $now; + $config{$host}{'wtime'} = 0; + $config{$host}{'warned-min-interval'} = 0; + $config{$host}{'warned-min-error-interval'} = 0; + + delete $cache{$host}{'warned-min-interval'}; + delete $cache{$host}{'warned-min-error-interval'}; + } + + return $update; +} +###################################################################### +## header_ok +###################################################################### +sub header_ok { + my ($host, $line) = @_; + my $ok = 0; + + if ($line =~ m%^s*HTTP/1.*\s+(\d+)%i) { + my $result = $1; + + if ($result eq '200') { + $ok = 1; + + } elsif ($result eq '401') { + failed("updating %s: authorization failed (%s)", $host, $line); + } + + } else { + failed("updating %s: unexpected line (%s)", $host, $line); + } + return $ok; +} +###################################################################### +## nic_dyndns1_examples +###################################################################### +sub nic_dyndns1_examples { + return <\s*(.*)\s*%i; + $return_code = $1 if $line =~ m%^return\s+code\s*:\s*(.*)\s*$%i; + $error_code = $1 if $line =~ m%^error\s+code\s*:\s*(.*)\s*$%i; + } + + if ($return_code ne 'NOERROR' || $error_code ne 'NOERROR' || !$title) { + $config{$h}{'status'} = 'failed'; + $title = "incomplete response from $config{$h}{server}" unless $title; + warning("SENT: %s", $url) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s: %s", $h, $title); + + } else { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: %s: IP address set to %s (%s)", $h, $return_code, $ip, $title); + } + } +} +###################################################################### +## nic_dyndns2_updateable +###################################################################### +sub nic_dyndns2_updateable { + my $host = shift; + my $update = 0; + + if ($config{$host}{'mx'} ne $cache{$host}{'mx'}) { + info("forcing updating %s because 'mx' has changed to %s.", $host, $config{$host}{'mx'}); + $update = 1; + + } elsif ($config{$host}{'mx'} && (ynu($config{$host}{'backupmx'},1,2,3) ne ynu($config{$host}{'backupmx'},1,2,3))) { + info("forcing updating %s because 'backupmx' has changed to %s.", $host, ynu($config{$host}{'backupmx'},"YES","NO","NO")); + $update = 1; + + } elsif ($config{$host}{'static'} ne $cache{$host}{'static'}) { + + info("forcing updating %s because 'static' has changed to %s.", $host, ynu($config{$host}{'static'},"YES","NO","NO")); + $update = 1; + + } + return $update; +} +###################################################################### +## nic_dyndns2_examples +###################################################################### +sub nic_dyndns2_examples { + return < 'Bad authorization (username or password)', + 'badsys' => 'The system parameter given was not valid', + + 'notfqdn' => 'A Fully-Qualified Domain Name was not provided', + 'nohost' => 'The hostname specified does not exist in the database', + '!yours' => 'The hostname specified exists, but not under the username currently being used', + '!donator' => 'The offline setting was set, when the user is not a donator', + '!active' => 'The hostname specified is in a Custom DNS domain which has not yet been activated.', + 'abuse', => 'The hostname specified is blocked for abuse; contact support@dyndns.org to be unblocked', + + 'numhost' => 'System error: Too many or too few hosts found. Contact support@dyndns.org', + 'dnserr' => 'System error: DNS error encountered. Contact support@dyndns.org', + + 'nochg' => 'No update required; unnecessary attempts to change to the current address are considered abusive', + ); + + ## update each set of hosts that had similar configurations + foreach my $sig (keys %groups) { + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:","updating %s", $hosts); + + ## Select the DynDNS system to update + my $url = "http://$config{$h}{'server'}/nic/update?system="; + if ($config{$h}{'custom'}) { + warning("updating %s: 'custom' and 'static' may not be used together. ('static' ignored)", $hosts) + if $config{$h}{'static'}; +# warning("updating %s: 'custom' and 'offline' may not be used together. ('offline' ignored)", $hosts) +# if $config{$h}{'offline'}; + $url .= 'custom'; + + } elsif ($config{$h}{'static'}) { +# warning("updating %s: 'static' and 'offline' may not be used together. ('offline' ignored)", $hosts) +# if $config{$h}{'offline'}; + $url .= 'statdns'; + + } else { + $url .= 'dyndns'; + } + + $url .= "&hostname=$hosts"; + $url .= "&myip="; + $url .= $ip if $ip; + + ## some args are not valid for a custom domain. + $url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0); + if ($config{$h}{'mx'}) { + $url .= "&mx=$config{$h}{'mx'}"; + $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); + } + + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); + + my @reply = split /\n/, $reply; + my $state = 'header'; + foreach my $line (@reply) { + if ($state eq 'header') { + $state = 'body'; + + } elsif ($state eq 'body') { + $state = 'results' if $line eq ''; + + } elsif ($state =~ /^results/) { + $state = 'results2'; + + my ($status, $ip) = split / /, lc $line; + my $h = shift @hosts; + + $config{$h}{'status'} = $status; + if ($status eq 'good') { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + success("updating %s: %s: IP address set to %s", $h, $status, $ip); + + } elsif (exists $errors{$status}) { + if ($status eq 'nochg') { + warning("updating %s: %s: %s", $h, $status, $errors{$status}); + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + + } else { + failed("updating %s: %s: %s", $h, $status, $errors{$status}); + } + + } elsif ($status =~ /w(\d+)(.)/) { + my ($wait, $units) = ($1, lc $2); + my ($sec, $scale) = ($wait, 1); + + ($scale, $units) = (1, 'seconds') if $units eq 's'; + ($scale, $units) = (60, 'minutes') if $units eq 'm'; + ($scale, $units) = (60*60, 'hours') if $units eq 'h'; + + $sec = $wait * $scale; + $config{$h}{'wtime'} = $now + $sec; + warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); + + } else { + failed("updating %s: %s: unexpected status (%s)", $h, $line); + } + } + } + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) + if $state ne 'results2'; + } +} +###################################################################### +## nic_concont_examples +###################################################################### +sub nic_concont_examples { + return </i, @reply) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + $config{$h}{'status'} = 'failed'; + warning("SENT: %s", $url) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s: Invalid reply.", $h); + } + } +} +###################################################################### +## nic_zoneedit1_examples +###################################################################### +sub nic_zoneedit1_examples { + return < +# +# +###################################################################### +sub nic_zoneedit1_update { + debug("\nnic_zoneedit1_update -------------------"); + + ## group hosts with identical attributes together + my %groups = group_hosts_by([ @_ ], [ qw(login password server) ]); + + ## update each set of hosts that had similar configurations + foreach my $sig (keys %groups) { + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:","updating %s", $hosts); + + my $url = ''; + $url .= "http://$config{$h}{'server'}/auth/dynamic.html"; + $url .= "?host=$hosts"; + $url .= "&dnsto=$ip" if $ip; + + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); + + my @reply = split /\n/, $reply; + foreach my $line (@reply) { + if ($line =~ /^[^<]*<(SUCCESS|ERROR)\s+([^>]+)>(.*)/) { + my ($status, $assignments, $rest) = ($1, $2, $3); + my ($left, %var) = parse_assignments($assignments); + + if (keys %var) { + my ($status_code, $status_text, $status_ip) = ('999', '', $ip); + $status_code = $var{'CODE'} if exists $var{'CODE'}; + $status_text = $var{'TEXT'} if exists $var{'TEXT'}; + $status_ip = $var{'IP'} if exists $var{'IP'}; + + if ($status eq 'SUCCESS' || ($status eq 'ERROR' && $var{'CODE'} eq '707')) { + $config{$h}{'ip'} = $status_ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + + success("updating %s: IP address set to %s (%s: %s)", $h, $ip, $status_code, $status_text); + + } else { + $config{$h}{'status'} = 'failed'; + failed("updating %s: %s: %s", $h, $status_code, $status_text); + } + shift @hosts; + $h = $hosts[0]; + $hosts = join(',', @hosts); + } + $line = $rest; + redo if $line; + } + } + failed("updating %s: no response from %s", $hosts, $config{$h}{'server'}) + if @hosts; + } +} +###################################################################### +## nic_easydns_updateable +###################################################################### +sub nic_easydns_updateable { + my $host = shift; + my $update = 0; + + if ($config{$host}{'mx'} ne $cache{$host}{'mx'}) { + info("forcing updating %s because 'mx' has changed to %s.", $host, $config{$host}{'mx'}); + $update = 1; + + } elsif ($config{$host}{'mx'} && (ynu($config{$host}{'backupmx'},1,2,3) ne ynu($config{$host}{'backupmx'},1,2,3))) { + info("forcing updating %s because 'backupmx' has changed to %s.", $host, ynu($config{$host}{'backupmx'},"YES","NO","NO")); + $update = 1; + + } elsif ($config{$host}{'static'} ne $cache{$host}{'static'}) { + + info("forcing updating %s because 'static' has changed to %s.", $host, ynu($config{$host}{'static'},"YES","NO","NO")); + $update = 1; + + } + return $update; +} +###################################################################### +## nic_easydns_examples +###################################################################### +sub nic_easydns_examples { + return < [ $_ ] } @_; + + my %errors = ( + 'NOACCESS' => 'Authentication failed. This happens if the username/password OR host or domain are wrong.', + 'NOSERVICE'=> 'Dynamic DNS is not turned on for this domain.', + 'ILLEGAL' => 'Client sent data that is not allowed in a dynamic DNS update.', + 'TOOSOON' => 'Update frequency is too short.', + ); + + ## update each set of hosts that had similar configurations + foreach my $sig (keys %groups) { + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:","updating %s", $hosts); + + #'http://members.easydns.com:80/dyn/ez-ipupdate.php?action=edit&myip=10.20.30.40&host_id=test.burry.ca&' + + my $url; + $url = "http://$config{$h}{'server'}/dyn/ez-ipupdate.php?action=edit"; + $url .= "&host_id=$hosts"; + $url .= "&myip="; + $url .= $ip if $ip; + $url .= "&wildcard=" . ynu($config{$h}{'wildcard'}, 'YES', 'NO', 'NO') if defined $config{$h}{'wildcard'}; + + if ($config{$h}{'mx'}) { + $url .= "&mx=$config{$h}{'mx'}"; + $url .= "&backmx=" . ynu($config{$h}{'backupmx'}, 'YES', 'NO'); + } + + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); + + my @reply = split /\n/, $reply; + my $state = 'header'; + foreach my $line (@reply) { + if ($state eq 'header') { + $state = 'body'; + + } elsif ($state eq 'body') { + $state = 'results' if $line eq ''; + + } elsif ($state =~ /^results/) { + $state = 'results2'; + + my ($status) = $line =~ /^(\S*)\b.*/; + my $h = shift @hosts; + + $config{$h}{'status'} = $status; + if ($status eq 'NOERROR') { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + success("updating %s: %s: IP address set to %s", $h, $status, $ip); + + } elsif ($status =~ /TOOSOON/) { + ## make sure we wait at least a little + my ($wait, $units) = (5, 'm'); + my ($sec, $scale) = ($wait, 1); + + ($scale, $units) = (1, 'seconds') if $units eq 's'; + ($scale, $units) = (60, 'minutes') if $units eq 'm'; + ($scale, $units) = (60*60, 'hours') if $units eq 'h'; + $config{$h}{'wtime'} = $now + $sec; + warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); + + } elsif (exists $errors{$status}) { + failed("updating %s: %s: %s", $h, $line, $errors{$status}); + + } else { + failed("updating %s: %s: unexpected status (%s)", $h, $line); + } + last; + } + } + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) + if $state ne 'results2'; + } +} +###################################################################### + +###################################################################### +## nic_dnspark_updateable +###################################################################### +sub nic_dnspark_updateable { + my $host = shift; + my $update = 0; + + if ($config{$host}{'mx'} ne $cache{$host}{'mx'}) { + info("forcing updating %s because 'mx' has changed to %s.", $host, $config{$host}{'mx'}); + $update = 1; + + } elsif ($config{$host}{'mx'} && ($config{$host}{'mxpri'} ne $cache{$host}{'mxpri'})) { + info("forcing updating %s because 'mxpri' has changed to %s.", $host, $config{$host}{'mxpri'}); + $update = 1; + } + return $update; +} +###################################################################### +## nic_dnspark_examples +###################################################################### +sub nic_dnspark_examples { + return < [ $_ ] } @_; + + my %errors = ( + 'nochange' => 'No changes made to the hostname(s). Continual updates with no changes lead to blocked clients.', + 'nofqdn' => 'No valid FQDN (fully qualified domain name) was specified', + 'nohost'=> 'An invalid hostname was specified. This due to the fact the hostname has not been created in the system. Creating new host names via clients is not supported.', + 'abuse' => 'The hostname specified has been blocked for abuse.', + 'unauth' => 'The username specified is not authorized to update this hostname and domain.', + 'blocked' => 'The dynamic update client (specified by the user-agent) has been blocked from the system.', + 'notdyn' => 'The hostname specified has not been marked as a dynamic host. Hosts must be marked as dynamic in the system in order to be updated via clients. This prevents unwanted or accidental updates.', + ); + + ## update each set of hosts that had similar configurations + foreach my $sig (keys %groups) { + my @hosts = @{$groups{$sig}}; + my $hosts = join(',', @hosts); + my $h = $hosts[0]; + info("setting IP address to %s for %s", $ip, $hosts); + verbose("UPDATE:","updating %s", $hosts); + + #'http://www.dnspark.com:80/visitors/update.html?myip=10.20.30.40&hostname=test.burry.ca' + + my $url; + $url = "http://$config{$h}{'server'}/visitors/update.html"; + $url .= "?hostname=$hosts"; + $url .= "&myip="; + $url .= $ip if $ip; + + if ($config{$h}{'mx'}) { + $url .= "&mx=$config{$h}{'mx'}"; + $url .= "&mxpri=" . $config{$h}{'mxpri'}; + } + + my $reply = geturl(opt('proxy'), $url, $config{$h}{'login'}, $config{$h}{'password'}); + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}); + last; + } + last if !header_ok($hosts, $reply); + + my @reply = split /\n/, $reply; + my $state = 'header'; + foreach my $line (@reply) { + if ($state eq 'header') { + $state = 'body'; + + } elsif ($state eq 'body') { + $state = 'results' if $line eq ''; + + } elsif ($state =~ /^results/) { + $state = 'results2'; + + my ($status) = $line =~ /^(\S*)\b.*/; + my $h = pop @hosts; + + $config{$h}{'status'} = $status; + if ($status eq 'ok') { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + success("updating %s: %s: IP address set to %s", $h, $status, $ip); + + } elsif ($status =~ /TOOSOON/) { + ## make sure we wait at least a little + my ($wait, $units) = (5, 'm'); + my ($sec, $scale) = ($wait, 1); + + ($scale, $units) = (1, 'seconds') if $units eq 's'; + ($scale, $units) = (60, 'minutes') if $units eq 'm'; + ($scale, $units) = (60*60, 'hours') if $units eq 'h'; + $config{$h}{'wtime'} = $now + $sec; + warning("updating %s: %s: wait $wait $units before further updates", $h, $status, $ip); + + } elsif (exists $errors{$status}) { + failed("updating %s: %s: %s", $h, $line, $errors{$status}); + + } else { + failed("updating %s: %s: unexpected status (%s)", $h, $line); + } + last; + } + } + failed("updating %s: Could not connect to %s.", $hosts, $config{$h}{'server'}) + if $state ne 'results2'; + } +} + +###################################################################### + +###################################################################### +## nic_namecheap_examples +###################################################################### +sub nic_namecheap_examples { + return <0/i, @reply) { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + $config{$h}{'status'} = 'good'; + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + $config{$h}{'status'} = 'failed'; + warning("SENT: %s", $url) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s: Invalid reply.", $h); + } + } +} + +###################################################################### + + +###################################################################### + +###################################################################### +## nic_sitelutions_examples +###################################################################### +sub nic_sitelutions_examples { + return </dev/null 2>&1 + ;; +esac diff --git a/svn/sample-etc_dhcpc_dhcpcd-eth0.exe b/svn/sample-etc_dhcpc_dhcpcd-eth0.exe new file mode 100644 index 0000000..437e92e --- /dev/null +++ b/svn/sample-etc_dhcpc_dhcpcd-eth0.exe @@ -0,0 +1,20 @@ +#!/bin/sh +###################################################################### +## $Id$ +###################################################################### +PATH=/usr/sbin:${PATH} + +## update the DNS server unless the IP address is a private address +## that may be used as an internal LAN address. This may be true if +## other interfaces are assigned private addresses from internal +## DHCP server. + +case "$1" in +10.*) ;; +172.1[6-9].* | 172.2[0-9].* | 172.3[0-1].*) ;; +192.168.*) ;; +*) + logger -t dhcpcd IP address changed to $1 + ddclient -daemon=0 -syslog -use=ip -ip=$1 >/dev/null 2>&1 + ;; +esac diff --git a/svn/sample-etc_ppp_ip-up.local b/svn/sample-etc_ppp_ip-up.local new file mode 100644 index 0000000..b7a9025 --- /dev/null +++ b/svn/sample-etc_ppp_ip-up.local @@ -0,0 +1,40 @@ +#!/bin/sh +###################################################################### +## $Id$ +###################################################################### +## +## On my host, pppd invokes this script with args: +## /etc/ppp/ip-up.local ppp0 /dev/pts/1 115200 192.168.2.1 192.168.2.3 +## +## From the manual page for my pppd, these aguments are: +## scriptname interface-name tty-device speed local-IP-address remote-IP-address ipparam +## +## Some people have reported that their pppd returns their +## local-IP-address as $3. If that's also the case for you, +## you may need to change the $4 below to $3. This may not +## be necessary if your pppd also passes the local-ip-address +## in the environment as either PPP_LOCAL or IPLOCAL. +## +###################################################################### +PATH=/usr/sbin:${PATH} +IP= +IP=${IP:-$PPP_LOCAL} +IP=${IP:-$IPLOCAL} +IP=${IP:-$4} + +## update the DNS server unless the IP address is a private address +## that may be used as an internal LAN address (or PPtP tunnel). + +logger -t ddclient $0 $* +case "$IP" in +10.*) ;; +172.1[6-9].* | 172.2[0-9].* | 172.3[0-1].*) ;; +192.168.*) ;; +"") logger -t ddclient No local IP given so cannot update + ;; +*) ( + sleep 5 + ddclient -daemon=0 -syslog -use=if -if=$1 >/dev/null 2>&1 + ) & + ;; +esac diff --git a/svn/sample-etc_rc.d_init.d_ddclient b/svn/sample-etc_rc.d_init.d_ddclient new file mode 100755 index 0000000..ab6faf6 --- /dev/null +++ b/svn/sample-etc_rc.d_init.d_ddclient @@ -0,0 +1,91 @@ +#!/bin/bash +# +# ddclient This shell script takes care of starting and stopping +# ddclient. +# +# chkconfig: 2345 65 35 +# description: ddclient provides support for updating dynamic DNS services. + +CONF=/etc/ddclient/ddclient.conf +program=ddclient + +[ -f $CONF ] || exit 0 + +system=unknown +if [ -f /etc/fedora-release ]; then + system=fedora +elif [ -f /etc/redhat-release ]; then + system=redhat +elif [ -f /etc/debian_version ]; then + system=debian +fi + +PID='' +if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then + . /etc/init.d/functions + PID=`pidofproc $program` +else + PID=`ps -aef | grep "$program - sleep" | grep -v grep | awk '{print $2}'` +fi + +PATH=/usr/sbin:/usr/local/sbin:${PATH} +export PATH + +# See how we were called. +case "$1" in + start) + # Start daemon. + DELAY=`grep -v '^\s*#' $CONF | grep -i -m 1 "daemon" | awk -F '=' '{print $2}'` + if [ -z "$DELAY" ] ; then + DELAY="-daemon 300" + else + DELAY='' + fi + echo -n "Starting ddclient: " + if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then + daemon $program $DELAY + else + ddclient $DELAY + fi + echo + ;; + stop) + # Stop daemon. + echo -n "Shutting down ddclient: " + if [ -n "$PID" ] ; then + if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then + killproc $program + else + kill $PID + fi + else + echo "ddclient is not running" + fi + echo + ;; + restart) + $0 stop + $0 start + ;; + status) + if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then + status $program + else + if test "$PID" + then + for p in $PID + do + echo "$program (pid $p) is running" + done + else + echo "$program is stopped" + fi + fi + ;; + *) + echo "Usage: ddclient {start|stop|restart|status}" + exit 1 +esac + +exit 0 + diff --git a/svn/sample-etc_rc.d_init.d_ddclient.lsb b/svn/sample-etc_rc.d_init.d_ddclient.lsb new file mode 100755 index 0000000..01f06e1 --- /dev/null +++ b/svn/sample-etc_rc.d_init.d_ddclient.lsb @@ -0,0 +1,66 @@ +#!/bin/sh +# +# ddclient This shell script takes care of starting and stopping +# ddclient. +# +# chkconfig: 2345 65 35 +# description: ddclient provides support for updating dynamic DNS services. +# +# Above is for RedHat and now the LSB part +### BEGIN INIT INFO +# Provides: ddclient +# Required-Start: $syslog $remote_fs +# Should-Start: $time ypbind sendmail +# Required-Stop: $syslog $remote_fs +# Should-Stop: $time ypbind sendmail +# Default-Start: 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: ddclient provides support for updating dynamic DNS services +# Description: ddclient is a Perl client used to update dynamic DNS +# entries for accounts on many dynamic DNS services and +# can be used on many types of firewalls +### END INIT INFO +# +# $Id$ +# +### + +[ -f /etc/ddclient/ddclient.conf ] || exit 0 + +DDCLIENT_BIN=/usr/sbin/ddclient + +# +# LSB Standard (SuSE,RedHat,...) +# +if [ -f /lib/lsb/init-functions ] ; then + . /lib/lsb/init-functions +fi + +# See how we were called. +case "$1" in + start) + echo -n "Starting ddclient " + start_daemon $DDCLIENT_BIN -daemon 300 + rc_status -v + ;; + stop) + echo -n "Shutting down ddclient " + killproc -TERM `basename $DDCLIENT_BIN` + rc_status -v + ;; + restart) + $0 stop + $0 start + rc_status + ;; + status) + echo -n "Checking for service ddclient " + checkproc `basename $DDCLIENT_BIN`w + rc_status -v + ;; + *) + echo "Usage: ddclient {start|stop|restart|status}" + exit 1 +esac + +exit 0 diff --git a/svn/sample-etc_rc.d_init.d_ddclient.redhat b/svn/sample-etc_rc.d_init.d_ddclient.redhat new file mode 100755 index 0000000..a81b8cb --- /dev/null +++ b/svn/sample-etc_rc.d_init.d_ddclient.redhat @@ -0,0 +1,41 @@ +#!/bin/sh +# $Id$ +# ddclient This shell script takes care of starting and stopping +# ddclient. +# +# chkconfig: 2345 65 35 +# description: ddclient provides support for updating dynamic DNS services. + +[ -f /etc/ddclient/ddclient.conf ] || exit 0 + +. /etc/rc.d/init.d/functions + +# See how we were called. +case "$1" in + start) + # Start daemon. + echo -n "Starting ddclient: " + touch /var/lock/subsys/ddclient + daemon ddclient -daemon 300 + echo + ;; + stop) + # Stop daemon. + echo -n "Shutting down ddclient: " + killproc ddclient + echo + rm -f /var/lock/subsys/ddclient + ;; + restart) + $0 stop + $0 start + ;; + status) + status ddclient + ;; + *) + echo "Usage: ddclient {start|stop|restart|status}" + exit 1 +esac + +exit 0