--- /dev/null
+#! /bin/sh
+
+set -e
+. ./dyndns.conf
+
+## Check that the environment is set up properly.
+for i in DYNDNS_ZONE DYNDNS_HOST DYNDNS_SERVER DYNDNS_KEY SSH_CLIENT; do
+ eval havep=\${$i+t}\${$i-nil}
+ case $havep in nil) echo >&2 "$0: variable $i unset"; exit 2 ;; esac
+done
+
+## Find the client address. This may be useful.
+set -- $SSH_CLIENT; client=$1
+
+## Parse the commad line.
+set -- $SSH_ORIGINAL_COMMAND
+
+fail_usage () {
+ cat >&2 <<EOF
+usage: $0 COMMAND ARGS...
+
+Commands:
+ set [-force] HOST [ADDR]
+ unset HOST
+EOF
+ exit 1
+}
+getarg='case $# in 0) fail_usage ;; esac; arg=$1; shift'
+doneargs='case $# in 0) ;; *) fail_usage ;; esac'
+
+checkhost () {
+ host=$1
+
+ matchp=nil
+ for pat in $DYNDNS_HOST; do
+ case "$host" in $pat) matchp=t ;; esac
+ done
+ case $matchp in nil) echo >&2 "$0: hostname not permitted"; exit 2 ;; esac
+}
+
+doupdate () {
+ cmd=$1
+
+nsupdate -k "$DYNDNS_KEY" <<EOF
+server $DYNDNS_SERVER
+zone $DYNDNS_ZONE
+$cmd
+send
+EOF
+}
+
+eval $getarg; cmd=$arg
+case "$cmd" in
+ set)
+ forcep=nil
+ eval $getarg
+ case "$arg" in -force) forcep=t; eval $getarg ;; esac
+ host=$arg
+ case "$#,$forcep,$1" in
+ 0,nil,*) addr=$client ;;
+ 0,t,*) fail_usage ;;
+ *,nil,"$client" | *,t,*) addr=$1; shift ;;
+ *)
+ echo >&2 "$0: incorrect address (wanted = $2; found = $addr)"
+ exit 3
+ ;;
+ esac
+ eval $doneargs
+ checkhost "$host"
+ case $addr in
+ *:*) rrtype=AAAA ;;
+ *.*) rrtype=A ;;
+ *) echo >&2 "$0: failed to parse new address"; exit 2 ;;
+ esac
+ name=$host.$DYNDNS_ZONE
+ doupdate "
+ update delete $name IN $rrtype
+ update add $name ${DYNDNS_TTL-14400} IN $rrtype $addr"
+ ;;
+ unset)
+ eval $getarg; host=$arg
+ eval $doneargs
+ checkhost "$host"
+ name=$host.$DYNDNS_ZONE
+ doupdate "update delete $name IN"
+ ;;
+ *)
+ fail_usage
+ ;;
+esac