FreedomBox/actions/dynamicdns

255 lines
6.9 KiB
Bash
Executable File

#!/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
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}"
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`
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 URL |awk '{print $2}'`
fi
}
doGetOpt()
{
while getopts ":s:d:u:p:I:" 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
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
}
doWriteCFG()
{
#always write to the inactive config - needs to be enabled vi "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
rm $STATUSFILE
#find the interface (always the default gateway interface)
DEFAULT=`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=5" >> $FILE
echo "execute=$0 success" >> $FILE
echo "wildcard" >> $FILE
#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 | 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" >> $FILE
#if this line is added to config file, ez-ipupdate will be launched on startup via init.d
echo "daemon" >> $FILE
fi
fi
}
doGetWANIP()
{
if [ $IPURL ];then
OUTFILE=`mktemp`
wget -4 -o /dev/null -O $OUTFILE $IPURL
WANIP=`cat $OUTFILE`
rm $OUTFILE
else
#no WAN IP found because of missing check URL
WANIP=${NOIP}
fi
echo $WANIP > $IPFILE
}
cmd=$1
shift
case $cmd in
configure)
doGetOpt $@
doWriteCFG
;;
start)
if [ "$(cat $HELPERCFG |grep ^NAT | awk '{print $2}')" = "no" ];then
mv $CFG_disabled $CFG
/etc/init.d/${TOOLNAME} start
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
[ -f $CFG_disabled ] && FILE=$CFG_disabled
[ -f $CFG ] && FILE=$CFG
RESULT=0
#if we know our WAN IP, only update if IP changes
if [ "$OLDIP" != "$WANIP" -a "${WANIP}" != ${NOIP} ];then
${UPDATE_TOOL} -c $FILE
RESULT=$?
[ $RESULT -eq 0 ] && $0 success
cat /proc/uptime |awk '{print $1}' |cut -d . -f 1 > $LASTUPDATE
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
${UPDATE_TOOL} -c $FILE
RESULT=$?
[ $RESULT -eq 0 ] && $0 success
cat /proc/uptime |awk '{print $1}' |cut -d . -f 1> $LASTUPDATE
fi
fi
if [ $RESULT -ne 0 ];then
$0 failed
fi
;;
stop)
rm $CRONJOB 2> /dev/null
/etc/init.d/${TOOLNAME} stop
mv $CFG $CFG_disabled
;;
success)
DATE=`date`
echo "last update done ($DATE)" > $STATUSFILE
;;
failed)
DATE=`date`
echo "last update failed ($DATE)" > $STATUSFILE
;;
get-last-success)
if [ -f $STATUSFILE ];then
cat $STATUSFILE
else
echo "no update recorded since last config change"
fi
;;
status)
doReadCFG
PROC=`pgrep ${TOOLNAME}`
if [ -f $CRONJOB ];then
echo enabled
elif [ ! -z $PROC ];then
echo enabled
else
echo disabled
fi
echo $server
echo $host
echo $user
echo $pass
echo $IPURL
;;
get-timer)
echo $UPDATEMINUTES
;;
clean)
rm ${CFGDIR}/*
;;
*)
echo "usage: status|configure <options>|start|stop|update|get-nat|clean|success|failed"
echo ""
echo "options are:"
echo "-s <server> Gnudip Server address"
echo "-d <domain> Domain to be updated"
echo "-u <user> Account username"
echo "-p <password> Account Password"
echo "-I <IP check URL> A URL which returns the IP of the client who is requesting"
echo ""
echo "update do a one time update"
echo "clean delete configuration"
echo "success store update success"
echo "failed store update failure"
echo "get-nat return the detected nat type"
;;
esac
exit 0