#!/bin/bash ## # SDDNS update script # # @copyright 2013 Steffen Vogel # @license http://www.gnu.org/licenses/gpl.txt GNU Public License # @author Steffen Vogel # @link http://www.steffenvogel.de ## ## # This file is part of sddns # # sddns is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # any later version. # # sddns is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with sddns. If not, see . ## # default options VER=4 TTL=120 USER=anonymous ZONE=0l.de HOST=$(hostname) function usage { cat <<-EOF Usage: sddns.sh [-4,-6] [-p PASS] [-t TTL] [-i IF] [-z ZONE] [-d] [-D] [HOST] Options: -u optional user for admin permissions -p is the password from the webservice otherwise prompted -t is the time to live in seconds -i use the ip from this nic -z nameserver zone -4 update A record (default) -6 update AAAA record -D live monitor interface for changing addresses -d enable verbose output -h show this help HOST is the hostname which you want to update defaults to the local hostname Example: sddns.sh -6 -t 3600 -i eth0 sea written by Steffen Vogel EOF } function deps() { FAILED=0 for DEP in $*; do if ! which ${DEP} &>/dev/null; then echo -e "This script requires ${DEP} to run but it is not installed." ((FAILED++)) fi done return ${FAILED} } function parse() { if [[ $* =~ ${RE} && ${BASH_REMATCH[1]} == "${IF}" ]]; then echo ${BASH_REMATCH[2]} fi } function update() { RDATA=$1 TYPE=$2 WAIT=1 URL="http://d.0l.de/update.txt?host=${HOST}&zone=${ZONE}&ttl=${TTL}&class=IN&type=${TYPE}&rdata=${RDATA}&debug=${DEBUG}" if (( $DEBUG )); then echo "Updating record: $URL"; fi while true; do CODE=$(curl -w %{http_code} -s -o /dev/stderr -u "${USER}:${PASS}" "$URL") 2>&1 if [ $CODE -eq 0 ]; then if (( $DEBUG )); then echo "Sleeping for ${WAIT} secs..."; fi sleep $WAIT; # wait until interface is ready WAIT=$(($WAIT*2)) elif [ $CODE -ge 500 ]; then if (( $DEBUG )); then echo "Request failed. Aborting.."; fi return 1 else break fi done return 0 } function get() { curl -${VER} -s http://d.0l.de/ip.txt | cut -f 3 } function query() { dig $TYPE $HOST.$ZONE @ns0.0l.de +short } # check dependencies if ! deps dig curl ip sed cut; then echo -e "Unmet dependencies: Aborting!" exit 1 fi # parse arguments while getopts "z:p:u:t:i:Dhd46" OPT; do case ${OPT} in p) PASS=${OPTARG} ;; u) USER=${OPTARG} ;; t) TTL=${OPTARG} ;; 4) VER=4 ;; 6) VER=6 ;; i) IF=${OPTARG} ;; D) DAEMON=1 ;; d) DEBUG=${OPTARG:-5} ;; h) usage exit 0 ;; *) usage exit 1 esac done # clear all options and reset the command line shift $((OPTIND-1)) # parsing host if [ -n "$1" ]; then HOST=$1 else echo -e "missing host" exit 1 fi # prompting for password if [ -z "${PASS}" ]; then read -s -p "password: " PASS echo fi # setup regular expression and record type if [ ${VER} -eq 4 ]; then RE='^[0-9]+: +([^ ]+) +inet +([^/]+)/([0-9]+) brd [^ ]+ +scope +global' TYPE="A" else RE='^[0-9]+: +([^ ]+) +inet6 +([^/]+)/([0-9]+) +scope +global' TYPE="AAAA" fi # lets go if [ -z "${IF}" ]; then IP=$(get) if [ -n "${IP}" ]; then update "${IP}" "${TYPE}" || exit else echo -e "failed to get ip from net" exit 1 fi else while read LINE; do IP=$(parse ${LINE}) if [ -n "${IP}" ]; then update "${IP}" "${TYPE}" || exit fi done < <(ip -o -${VER} address show && (( ${DAEMON} )) && ip -o -${VER} monitor address) fi