#!/bin/sh # # ifup_nsupdate # # DESCRIPTION: # Goes in your LEAF system's /etc/network/if-up.d directory (or the equivalent # directory on a normal Linux box) to update your name server with your # dynamically-assigned IP address (e.g. from PPPoE). Requires a TSIG # public/private keyfile pair generated by BIND 8's dnskeygen or BIND 9's # dns-seckeygen to reside in /etc/nsupdate. The name of the private keyfile # and a few other variables must be personalized below for this script to # work! # # For more information on TSIG-based dynamic DNS, see the BIND documentation # at and/or Jason Bodnar's very helpful "Dynamic DNS # for the Home User" at (but # ignore the part of that document talking about HTTP-based dynamic updates). # # COPYRIGHT: # This file is Copyright (C) 2002 by its authors, and is released under the # GNU General Public License . # # AUTHORS: # DH = Dan # # DATE BY REVISION # ========== == ============================================================== # 2002-07-29 DH Original. ## The variables in this section MUST be configured: # The FQDN you want to register as having your dynamic IP. #DYNAMIC_IP_HOSTNAME=... # The interface that has your external IP address bound to it. This is ppp0 # for PPP/PPPoE, or eth0 in direct-routed setups (with IPs assigned by DHCP). EXTERNAL_IP_IFACE=ppp0 # Ordinarily nsupdate would figure out the responsible nameserver automatically, # but on LEAF it tries to contact the caching nameserver at 127.0.0.1. Note # that the nameserver must be specified by IP address, not DNS name, because # dnscache won't have started when the interface is first being brought up. #NAMESERVER= # The public keyfile (K.++.key) must be in this same dir # (which is intentionally only readable by root to protect the private key). #PRIVATE_KEYFILE=/etc/nsupdate/K.++.private # Now check that the user has been in here configuring (and made it to the last # required variable); abort cleanly if not. if [ x"$PRIVATE_KEYFILE" = x ]; then echo "ERROR: $0 has not been configured. Aborting." exit 1 fi ## These settings can usually be left as-is: # ifup sets $IFACE in our environment (verified for the PPPoE case, at least), # but to allow this script to be called directly, we need to set IFACE here. if [ x"$IFACE" = x ]; then IFACE=$EXTERNAL_IP_IFACE fi # For PPPoE, at least, the interface isn't actually up when we first get # called, but it'll go up in the background if we wait a bit. # $IFACE_UP_WAIT_TIME is how many seconds to wait between checks for the # interface being up. $IFACE_UP_WAIT_MAX_RETRIES is how many times we'll try # waiting before we give up. IFACE_UP_WAIT_MAX_RETRIES=12 IFACE_UP_WAIT_TIME=5 # nsupdate has a pretty short timeout (and as of this writing there's no # parameter to increase it) -- sometimes it fails just because the link is # slow or the server is busy. Try up to $NSUPDATE_MAX_RETRIES times and wait # $NSUPDATE_WAIT_TIME seconds between tries. NSUPDATE_MAX_RETRIES=3 NSUPDATE_WAIT_TIME=5 # -d has nsupdate do debugging output, including the DNS server's response. NSUPDATE_OPTIONS=-d # The desired time-to-live (in seconds) for this dynamic DNS setting. TTL=300 # If ifup isn't being run on the appropriate interface, exit now before we # potentially try to do an rdate (and of course try to do the update itself). if [ "$IFACE" != "$EXTERNAL_IP_IFACE" ]; then exit fi # If the machine's time is way out-of-sync with the nameserver (as it will be # if the machine's CMOS clock is set to the local time but /etc/localtime is # still the installation-default of UTC), the DNS update will fail. Generally # it should be enough to install the appropriate /usr/share/zoneinfo file and # point /etc/localtime at it, but if the clock is still too far off from the # nameserver's you might need to uncomment this line (note it'll only be useful # if the nameserver's time/tcp port is open -- if it's not, you'll need to look # to an NTP solution). #rdate $NAMESERVER ## Ordinarily, you shouldn't need to modify anything below this line. this_script=`basename $0` # For testing purposes, you can set environment variable $IP to arbitrary val. if [ x"$IP" = x ]; then times_waited=0 while ! ip addr list $IFACE 2>/dev/null \ | grep "inet [0-9]" 1>/dev/null 2>&1; do if [ $times_waited = $IFACE_UP_WAIT_MAX_RETRIES ]; then echo "$this_script: Exceeded IFACE_UP_WAIT_MAX_RETRIES of"\ "$IFACE_UP_WAIT_MAX_RETRIES. Aborting." exit 1 fi times_waited=`expr $times_waited + 1` echo "$this_script: $IFACE not up yet. Sleeping"\ "$IFACE_UP_WAIT_TIME seconds (repetition $times_waited of"\ "$IFACE_UP_WAIT_MAX_RETRIES)." sleep $IFACE_UP_WAIT_TIME done IP=`ip addr list $IFACE | grep "inet [0-9]" \ | sed 's/^.*inet \(\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*$/\1/'` fi ADD_CMD="update add $DYNAMIC_IP_HOSTNAME $TTL A $IP\n" DELETE_CMD="update delete $DYNAMIC_IP_HOSTNAME A\n" SERVER_CMD="server $NAMESERVER\n" nsupdate_exit=1 times_nsupdated=0 while [ $nsupdate_exit != 0 ]; do echo -e "$SERVER_CMD$DELETE_CMD$ADD_CMD" \ | nsupdate $NSUPDATE_OPTIONS -k $PRIVATE_KEYFILE >/dev/null nsupdate_exit=$? times_nsupdated=`expr $times_nsupdated + 1` if [ $nsupdate_exit = 0 ]; then echo "$this_script: nsupdate succeeded." else echo -e "$this_script: nsupdate failed (try $times_nsupdated of"\ "$NSUPDATE_MAX_RETRIES).\c" if [ $times_nsupdated -lt $NSUPDATE_MAX_RETRIES ]; then echo " Sleeping $NSUPDATE_WAIT_TIME seconds before retry." sleep $NSUPDATE_WAIT_TIME else echo break fi fi done exit $nsupdate_exit