#!/bin/bash  

# modified by Hans-Christoph Steiner http://at.or.at/hans/misc
# CVS Info: $Id $

################################################################################
# NAME: updyn 
################################################################################
#  DESCRIPTION: 
#  A bash shell script to update your dynamic dns service with your
#  current ip address.  This will work with any dynamic dns service (like registerfly's
#  or other reseller of enom) that allows  you to call a url to update the dns.
#  If you don't know if yours does, read the support section for your service.
#  This script checks to see if the external ip address set for your hostname
#  (using the host command) It works even if you have a router making your
#  external ip different from your internal ip. 
################################################################################
# FEATURES:
#	-works behind a router (when external ip is different from internal ip)
#	-optional minimum time check
#	-does not update unless your actual ip is different from your assigned ip
#	 this is required by most dns services 
#	-can set it to update the dns every set number of days whether or not your ip has changed
################################################################################
# REQUIREMENTS:
################################################################################
#  - lynx, a text browser included in most linux distributions (see http://lynx.browser.org/)
#  - for an ssl commention, a secure ssl text browser (try lynx-ssl: http://www.bebits.com/app/1830) 
#  - bash (most linux distributions, could be used in other shells with minor modifications))
#  - a dynamic dns service that allows you to update the dns using a url (like
#  registerfly)
################################################################################
## INSTALLATION:
# 1. Make sure permissions are set to execute 
#      chmod 755 ./updyn
# 2. Copy to your /usr/bin or wherever your want
# 3. Edit Configuration section below as instructed in the comments. 
# 4. Add to your crontab to run 15 minutes or so:
#	crontab -e
#       15,30,45,59 * * * * /usr/bin/updyn > /dev/null       
# 5. That's it
###############################################################
#  "MIT License":
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions: The above copyright #
# notice and this permission notice shall be included in all copies or
# substantial portions of
# the Software.  
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
# EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
# OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
################################################################################
# TO DO (OR Suggested Improvements):
# - Command Line Options (verbose, debugs, etc.)
################################################################################
# HISTORY
#
# 0.1 Beta Release 1-17-04
#          - first beta relese - works for me but no promises!
################################################################################
# AUTHOR: Please send all comments, modifications,bugs, etc. to:
# DCD (ddruff@gemini1consulting.com)  
# http://www.gemini1consulting.com/tekhelp
# ABSOLUTELY NO SUPPORT and no guarantee of response. 
################################################################################
###########################END OF README#########################################


################################################################################
# START OF SCRIPT 
################################################################################

NAME=$(whoami)

#############################################
# Configuration
#############################################
# 1. Set the below variable to a url which gives you your external ip address
#   The ostrosoft one works for me - it must be one that just outputs text,
#   otherwise you are going to have to add code to parse the result so as to
#   assign the resulting ip to $IPADDRESS also see http://www.whatismyip.com/
#   but that requires some work in parsing (a regular express should catch it
#   easily).
################################################################################
	 
# This assigns your external ip address to the variable
# depending on your web getter of choice
if [ `which curl || echo NO` != "NO" ]; then
	 HTTP_GETTER="curl --silent"
elif [ `which wget || echo NO` != "NO" ]; then
	 HTTP_GETTER="wget --quiet --output-document -"
elif [ `which lynx || echo NO` != "NO" ]; then
	 HTTP_GETTER="lynx --dump"
else
	 echo "FATAL ERROR: curl, wget, or lynx required for $0 to run!!"
	 exit
fi

if [ $# -eq 4 ]; then
	 # if one argument, then use it as net device
	 CURRENT_IP_ADDRESS=`ifconfig $4 | \
        sed -n 's/.*inet[adr: ]*\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\).*/\1/p'`
#	 echo -n "used ifconfig $4 to get: "
elif [ $# -eq 3 ]; then
	 GET_IP_URL=http://checkip.dyndns.org/
	 
	 CURRENT_IP_ADDRESS=`${HTTP_GETTER} "$GET_IP_URL"`
#	 echo -n "used ${HTTP_GETTER} to get: "
# grab just the address from the result
	 CURRENT_IP_ADDRESS=`echo $CURRENT_IP_ADDRESS | \
        sed 's/.* \([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\).*/\1/'`
else
	 echo " "
	 echo "Usage $0 username password hostname [eth device]"
	 echo " "
	 echo "   username = dyndns.org account"
	 echo "   password = dyndns.org password"
	 echo "   hostname = dyndns.org dynamic hostname"
	 echo "   [eth device] = device to get IP from (optional, instead of checkip.dyndns.org)"
	 echo " "
	 exit
fi

#echo "$CURRENT_IP_ADDRESS"
################################################################################
# find which name resolution method will work
################################################################################

if [ `which host || echo NO` != "NO" ]; then
	 RESOLVER=host
elif [ `which nslookup || echo NO` != "NO" ]; then
	 RESOLVER=nslookup
else
	 echo "FATAL ERROR: host or nslookup required for $0 to run!!"
	 exit
fi

# for debugging
#RESOLVER=nslookup

################################################################################
# 2. Set path to ip tracking file. This file keeps track of when you last
# updated.
################################################################################

IP_DYNAMIC_LAST_UPDATED_FILE=/tmp/"$NAME"_last_dynamic_ip_update.txt

################################################################################
#  3. Set Minimum Interval In Minutes to Check. Some dynamic dns servers will
#  kick you off if you check more than once in a few minutes. Set to 0 if you
#  don't want to limit to any particular interval
################################################################################

MINIMUM_INTERVAL=0 # minutes

################################################################################
#  4.  Set Required_Interval - some dynamic dns servers will kick you off if
#      you don't update at least once every certain amount of days even if
#      your ip hasn't changed.  Set this to 0 if you don't want it to do the
#      mandatory update.
################################################################################

REQUIRED_INTERVAL=30 # days

################################################
# 5.  For each dynamic dns name, add your dns name to the DYNAMIC_HOST_NAME[X]
#     array, and add the applicable reset url to the URLS[X] array. Make sure
#     each url is surrounded by quotes. Here's an example using registryfly
#     url:
#
#     DYNAMIC_HOST_NAME[1]="www.mydomain.com"
#     URLS[1]="http://dynamic.registerfly.com/index.php?domain=mydomain.com&password=234sdr3k33423l&ipaddress=$CURRENT_IP_ADDRESS&host=www&sdd=Save+changes"
#
###############################################

# Uncomment the following 2 lines and add your own info 

# DYNAMIC_HOST_NAME[1]=       #name of domain in form of www.mydomain.com
# URLS[1]=               # name of 

# Add additional urls as desired in the format above, increasing the index by
# 1.  You can add as many as you want

# DynDNS.org
USERNAME=$1
PASSWORD=$2
DYNAMIC_HOST_NAME[0]=$3
URLS[0]="http://${USERNAME}:${PASSWORD}@members.dyndns.org/nic/update?system=dyndns&hostname=${DYNAMIC_HOST_NAME}&myip=${CURRENT_IP_ADDRESS}"


###########################################################
#End of Configuration
############################################################

############################
# Check Minimum Interval
############################

CURRENT_TIME_IN_SECONDS=$(date +"%s")


if [ -f "$IP_DYNAMIC_LAST_UPDATED_FILE" ]; then
	 TIME_LAST_UPDATED=$(more $IP_DYNAMIC_LAST_UPDATED_FILE)
else
    # if file is missing, set variable to make sure its checked now
    # and save file again
	 
	 let TIME_LAST_UPDATED="$CURRENT_TIME_IN_SECONDS-$MINIMUM_INTERVAL-1"
 	 echo $CURRENT_TIME_IN_SECONDS  > "$IP_DYNAMIC_LAST_UPDATED_FILE"
fi

if [ "$TIME_LAST_UPDATED" != "" ]; then
	 let MINUTES_SINCE_LAST_UPDATED="$CURRENT_TIME_IN_SECONDS-$TIME_LAST_UPDATED"
	 let MINUTES_SINCE_LAST_UPDATED="$MINUTES_SINCE_LAST_UPDATED/60"
    let DAYS_SINCE_LAST_UPDATED="$MINUTES_SINCE_LAST_UPDATED/1440"
	 
    # for debugging
	 #echo $MINUTES_SINCE_LAST_UPDATED		
	 #echo $DAYS_SINCE_LAST_UPDATED		
fi

# Exit if less than minimum interval
if [ "$MINIMUM_INTERVAL" -gt 0 -a "$MINUTES_SINCE_LAST_UPDATED" -lt "$MINIMUM_INTERVAL" ]; then
	 echo "No update: less than minimum interval ($MINUTES_SINCE_LAST_UPDATED since last update)"
    exit 
fi



#####################################################
# Now check the ip's and reset if necessary 
#####################################################	

index=0
element_count=${#URLS[@]}

while [ "$index" -lt "$element_count" ]; do
		# Compare ip address actually assigned to dynamic host name with your current ip address. if 
		# not correct, then reset
	 
      # get current ip 
	 
	 if [ $RESOLVER == "host" ]; then
		  CURRENT_HOST_IP="$(host -t a -R 2 ${DYNAMIC_HOST_NAME[$index]} | cut -d' ' -f 4)" 
	 elif [ $RESOLVER == "nslookup" ]; then
		  CURRENT_HOST_IP=`nslookup ${DYNAMIC_HOST_NAME[$index]} | tail -3 | sed -n 's/Address:.* \([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\).*/\1/p'`
	 else
		  echo "FATAL ERROR: 'host' or 'nslookup' not available (resolver: $RESOLVER)"
		  exit
	 fi

# for debugging
#	 echo "loop $index  $CURRENT_HOST_IP"

    # reset if actual ip of machine is not one assigned to name by dns or
    # required interval has passed
	 if [[ "$CURRENT_HOST_IP" != "$CURRENT_IP_ADDRESS" ]] || [ "$REQUIRED_INTERVAL" -lt "$DAYS_SINCE_LAST_UPDATED" -a  "$REQUIRED_INTERVAL" -gt 0 ] ; then
	     #echo ${HTTP_GETTER} `echo \'${URLS[$index]}\'`
	     exec ${HTTP_GETTER} `echo \'${URLS[$index]}\'` > /dev/null 2>&1
 		  echo $CURRENT_TIME_IN_SECONDS > "$IP_DYNAMIC_LAST_UPDATED_FILE"
		  echo "Updated ${DYNAMIC_HOST_NAME[$index]} to $CURRENT_IP_ADDRESS"
    	  let index="$index + 1" 
	 else
		  echo "No update: $CURRENT_HOST_IP is unchanged"
	 fi
	 
    let index="$index + 1" 
done

#The end
