#!/bin/bash #Todo: IPv6 #Todo: Other service types than gnudip (generic update URL) #Todo: GET WAN IP from Router via UPnP if supported PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin #static values WGET=$(which wget) WGETOPTIONS="-4 -o /dev/null -t 3 -T 3" EMPTYSTRING="none" NOIP="0.0.0.0" #how often do we poll for IP changes if we are behind a NAT? UPDATEMINUTES=5 #if we do not have a IP check URL, how often should we do a "blind" update UPDATEMINUTESUNKNOWN=3600 TOOLNAME=ez-ipupdate UPDATE_TOOL=$(which ${TOOLNAME}) #Dirs and filenames CFGDIR="/etc/${TOOLNAME}/" CFG="${CFGDIR}${TOOLNAME}.conf" CFG_disabled="${CFGDIR}${TOOLNAME}.inactive" IPFILE="${CFGDIR}${TOOLNAME}.currentIP" STATUSFILE="${CFGDIR}${TOOLNAME}.status" LASTUPDATE="${CFGDIR}/last-update" HELPERCFG="${CFGDIR}${TOOLNAME}-plinth.cfg" CRONJOB="/etc/cron.d/${TOOLNAME}" PIDFILE="/var/run/ez-ipupdate.pid" doGetOpt() { basicauth=0 ignoreCertError=0 while getopts ":s:d:u:p:I:U:c:b:" opt; do case $opt in s) server=$OPTARG ;; d) host=$OPTARG ;; u) user=$OPTARG ;; p) pass=$OPTARG ;; I) if [ "$OPTARG" != "$EMPTYSTRING" ];then ipurl=$OPTARG else ipurl="" fi ;; U) if [ "$OPTARG" != "$EMPTYSTRING" ];then updateurl=$OPTARG else updateurl="" fi ;; b) basicauth=$OPTARG ;; c) ignoreCertError=$OPTARG ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; esac done } doWriteCFG() { mkdir $CFGDIR 2> /dev/null #always write to the inactive config - needs to be enabled via "start" command later file=$CFG_disabled #reset the last update time echo 0 > $LASTUPDATE #reset the last updated IP echo "0.0.0.0" > $IPFILE #reset last update (if there is one) rm $STATUSFILE 2> /dev/null #find the interface (always the default gateway interface) default_interface=`ip route |grep default |awk '{print $5}'` #store the given options in ez-ipupdate compatible config file echo "host=$host" > $file echo "server=$server" >> $file echo "user=${user}:${pass}" >> $file echo "service-type=gnudip" >> $file echo "retrys=3" >> $file echo "wildcard" >> $file #store UPDATE URL params echo "POSTURL $updateurl" > $HELPERCFG echo "POSTAUTH $basicauth" >> $HELPERCFG echo "POSTSSLIGNORE $ignoreCertError" >> $HELPERCFG #check if we are behind a NAT Router echo "IPURL $ipurl" >> $HELPERCFG if [ -z $ipurl ];then echo "NAT unknown" >> $HELPERCFG else doGetWANIP ISGLOBAL=`ip addr ls $default_interface | grep $wanip` if [ -z $ISGLOBAL ];then #we are behind NAT echo "NAT yes" >> $HELPERCFG else #we are directly connected echo "NAT no" >> $HELPERCFG #if this file is added ez-ipupdate will take ip form this interface echo "interface=$default_interface" >> $file #if this line is added to config file, ez-ipupdate will be launched on startup via init.d echo "daemon" >> $file echo "execute=$0 success" >> $file fi fi } doReadCFG() { host="" server="" user="" pass="" ipurl="" file="" [ -f $CFG_disabled ] && file=$CFG_disabled [ -f $CFG ] && file=$CFG if [ ! -z $file ];then host=`cat $file 2> /dev/null |grep host |cut -d = -f 2` server=`cat $file 2> /dev/null |grep server |cut -d = -f 2 |grep -v ^\'\'` user=`cat $file 2> /dev/null |grep user |cut -d = -f 2 |cut -d : -f 1 ` pass=`cat $file 2> /dev/null |grep user |cut -d = -f 2 |cut -d : -f 2` fi if [ ! -z $HELPERCFG ];then ipurl=`cat $HELPERCFG 2> /dev/null |grep ^IPURL |awk '{print $2}' |grep -v ^\'\'` updateurl=`cat $HELPERCFG 2> /dev/null |grep POSTURL |awk '{print $2}' |grep -v ^\'\'` basicauth=`cat $HELPERCFG 2> /dev/null |grep POSTAUTH |awk '{print $2}' |grep -v ^\'\'` ignoreCertError=`cat $HELPERCFG 2> /dev/null |grep POSTSSLIGNORE |awk '{print $2}' |grep -v ^\'\'` fi } doStatus() { PROC=`pgrep ${TOOLNAME}` if [ -f $CRONJOB ];then echo enabled elif [ ! -z $PROC ];then echo enabled else echo disabled fi if [ ! -z $server ];then echo $server else echo disabled fi if [ ! -z $host ];then echo $host else echo disabled fi if [ ! -z $user ];then echo $user else echo disabled fi if [ ! -z $pass ];then echo $pass else echo disabled fi if [ ! -z $ipurl ];then echo $ipurl else echo disabled fi if [ ! -z $updateurl ];then echo $updateurl else echo disabled fi if [ ! -z $basicauth ];then echo $basicauth else echo disabled fi if [ ! -z $ignoreCertError ];then echo $ignoreCertError else echo disabled fi } doGetWANIP() { if [ ! -z $ipurl ];then outfile=`mktemp` $WGET $WGETOPTIONS -O $outfile $ipurl wanip=`cat $outfile` rm $outfile [ -z $wanip ] && wanip=${NOIP} else #no WAN IP found because of missing check URL wanip=${NOIP} fi } doUpdate() { if [ ! -z $server ];then start-stop-daemon -S -x ${UPDATE_TOOL} -m -p ${PIDFILE} -- -c $file fi if [ ! -z $updateurl ];then echo "todo" fi } cmd=$1 shift case $cmd in configure) doGetOpt $@ doWriteCFG ;; start) if [ "$(cat $HELPERCFG |grep ^NAT | awk '{print $2}')" = "no" ];then if [ -f $CFG -a ! -z $(cat $file 2> /dev/null |grep server |cut -d = -f 2 |grep -v ^\'\')];then mv $CFG_disabled $CFG /etc/init.d/${TOOLNAME} start fi if [ ! -z $(cat $HELPERCFG |grep ^POSTURL | awk '{print $2}') ];then echo "*/${UPDATEMINUTES} * * * * root $0 update" > $CRONJOB $0 update fi else echo "*/${UPDATEMINUTES} * * * * root $0 update" > $CRONJOB $0 update fi ;; get-nat) NAT=`cat $HELPERCFG 2> /dev/null |grep ^NAT | awk '{print $2}'` [ -z $NAT ] && NAT="unknown" echo $NAT ;; update) doReadCFG oldip=`cat $IPFILE` doGetWANIP echo $wanip > $IPFILE cfgfile="/tmp/none" [ -f $CFG_disabled ] && cfgfile=$CFG_disabled [ -f $CFG ] && cfgfile=$CFG cat $file |grep -v execute > ${cfgfile}.tmp mv ${cfgfile}.tmp ${cfgfile} echo "execute=$0 success ${wanip}" >> $cfgfile #if we know our WAN IP, only update if IP changes if [ "${oldip}" != "${wanip}" -a "${wanip}" != ${NOIP} ];then doUpdate fi #if we don't know our WAN IP do a blind update once a hour if [ "${wanip}" = ${NOIP} ];then uptime=`cat /proc/uptime |cut -d . -f 1` LAST=0 [ -f ${LASTUPDATE} ] && LAST=`cat $LASTUPDATE` diff=`expr $uptime - $LAST` if [ $diff -gt $UPDATEMINUTESUNKNOWN ];then doUpdate fi fi ;; stop) rm $CRONJOB 2> /dev/null /etc/init.d/${TOOLNAME} stop kill $(cat ${PIDFILE}) 2> /dev/null mv $CFG $CFG_disabled ;; success) date=`date` echo "last update done ($date)" > $STATUSFILE cat /proc/uptime |awk '{print $1}' |cut -d . -f 1 > $LASTUPDATE #if called from cronjob, the current IP is given as parameter if [ $# -eq 1 ];then echo $1 > $IPFILE else #if called from ez-ipupdate daemon, no WAN IP is given as parameter doGetWANIP echo $wanip > $IPFILE fi ;; failed) date=`date` echo "last update failed ($date)" > $STATUSFILE ;; get-last-success) if [ -f $STATUSFILE ];then cat $STATUSFILE else echo "no successful update recorded since last config change" fi ;; status) doReadCFG doStatus ;; get-timer) echo $UPDATEMINUTES ;; clean) rm ${CFGDIR}/* rm $CRONJOB ;; *) echo "usage: status|configure |start|stop|update|get-nat|clean|success [updated IP]|failed" echo "" echo "options are:" echo "-s Gnudip Server address" echo "-d Domain to be updated" echo "-u Account username" echo "-p Account Password" echo "-I A URL which returns the IP of the client who is requesting" echo "-U The update URL (a HTTP GET on this URL will be done)" echo "-c <1|0> disable SSL check on Update URL" echo "-b <1|0> use HTTP basic auth on Update URL" echo "" echo "update do a one time update" echo "clean delete configuration" echo "success store update success and optional the updated IP" echo "failed store update failure" echo "get-nat return the detected nat type" ;; esac exit 0