1
0
mirror of https://github.com/EV21/dynb.git synced 2025-12-26 16:39:32 +01:00

36 Commits

Author SHA1 Message Date
fcdddde456 📝 change default dns server setting 2021-09-13 16:06:06 +02:00
e2ddda5ba7 🎨 add shfmt params to pre-commit check 2021-09-13 15:58:31 +02:00
24aa20be3b 🎨 fix shell style 2021-09-13 15:58:29 +02:00
d92cdb2652 🔧 handle dns server selection 2021-09-13 15:58:29 +02:00
4643331534 ♻️ seperate parsing logic 2021-09-13 15:58:29 +02:00
fa15700e5d change git hooks and add shfmt 2021-09-13 15:58:29 +02:00
43b09d7145 📝 update CHANGELOG 2021-09-13 15:58:29 +02:00
3b543754b3 ♻️ normalizing pre-commit configuration to a top-level map 2021-09-13 15:58:28 +02:00
040aec7472 ♻️ refactorings 2021-09-13 15:58:28 +02:00
eda5a69da2 add pre-commit git hook for shellcheck 2021-09-13 15:58:21 +02:00
01eaa30523 refactor: ♻️ remove unused help message 2021-09-12 22:00:46 +02:00
30c5373705 📝 update README.md 2021-04-23 22:16:59 +02:00
4e26ff135d 📝 document environment variables 2021-04-23 18:08:44 +02:00
be2f4f3862 ♻️ refactor: method extractions and other beautifications 2021-04-23 18:02:16 +02:00
93c1ed18d0 🐛 fix loop and error handling in case of connection issues 2021-04-23 12:00:35 +02:00
2c23b1de6e 📝 document example of an docker-compose.yml file 2021-04-22 22:30:08 +02:00
f9507929da add Dockerfile 2021-04-22 22:17:49 +02:00
30e77c9722 📝 document loop mode and dig as requirement 2021-04-22 22:10:11 +02:00
bb1d514b50 add loop mode 2021-04-22 21:55:25 +02:00
c02dc68f17 📝 update example of .env in README.md 2021-04-21 13:45:45 +02:00
dcf9f1e7a2 ♻️ refactor: rename environment variables 2021-04-21 13:04:59 +02:00
4d28f55ce9 add support for Duck DNS as DynDNS2 provider 2021-04-04 16:31:42 +02:00
b8565eb38f add support for deSEC as DynDNS2 provider 2021-04-04 11:24:13 +02:00
ab330e9731 add completion
 add man page
2021-04-03 17:35:26 +02:00
262f7c3709 replace getopt with argbash 2021-04-03 14:06:03 +02:00
5210c35400 ♻️ refactor, fix and debug error handling 2021-01-27 17:52:15 +01:00
522a0f99bb ♻️ refactor main code 2021-01-26 22:23:03 +01:00
3bf6b69ae8 add interpretaton of status codes and act accordingly 2021-01-26 21:43:07 +01:00
d139022295 make network interface configurable 2021-01-26 21:43:07 +01:00
8997835903 🐛 fix sourcing of config file
♻️ do some shellcheck fixes
2021-01-26 21:43:07 +01:00
d6dc223794 add DynDNS2 support for dynv6.com 2021-01-26 21:43:07 +01:00
dc12f71d00 📝 add CHANGELOG.md 2021-01-26 21:43:07 +01:00
5ba730cff1 add .gitchangelog.rc 2021-01-26 21:43:07 +01:00
1104cf8505 📝 add example.env 2021-01-26 21:43:07 +01:00
99a446f4c7 📝 write README.md 2021-01-26 21:42:21 +01:00
f056e96e25 add dynb.sh 2021-01-26 21:24:33 +01:00
6 changed files with 548 additions and 427 deletions

11
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,11 @@
repos:
- repo: https://github.com/syntaqx/git-hooks
rev: v0.0.17
hooks:
- id: shellcheck
- id: shfmt
args:
- "-l" # list files whose formatting differs from shfmt's
- "-i 2" # indent: 0 for tabs (default), >0 for number of spaces
- "-ci" # switch cases will be indented
- "-w" # write result to file instead of stdout

View File

@@ -1,6 +1,23 @@
# Changelog # Changelog
## (unreleased)
### Documentation
* :memo: update README.md. [Eduard Veit]
### Other
* :recycle: normalizing pre-commit configuration to a top-level map. [Eduard Veit]
* :recycle: refactorings. [Eduard Veit]
* Feature: :sparkles: add pre-commit git hook for shellcheck. [Eduard Veit]
* Refactor: :recycle: remove unused help message. [Eduard Veit]
## 0.1.2 (2021-04-23) ## 0.1.2 (2021-04-23)
### Documentation ### Documentation

View File

@@ -141,12 +141,12 @@ services:
- DYNB_INTERVAL=60 - DYNB_INTERVAL=60
``` ```
## environment variables ## environment variables
| variable | default value | description | | variable | default value | description |
| --------------------- | --------------- | ----------- | | --------------------- | --------------- | --------------------------------------------- |
| DYNB_DYN_DOMAIN | undefined | required | | DYNB_DYN_DOMAIN | undefined | required; `dyndns.example.com` |
| DYNB_SERVICE_PROVIDER | undefined | required | | DYNB_SERVICE_PROVIDER | undefined | required; `deSEC`, `duckdns`, `dynv6`, `inwx` |
| DYNB_UPDATE_METHOD | undefined | required | | DYNB_UPDATE_METHOD | undefined | required; `dyndns` or `domrobot` (with inwx) |
| DYNB_IP_MODE | undefined | required | | DYNB_IP_MODE | undefined | required; `4`, `6` or `64` for both |
| DYNB_USERNAME | undefined | the requirement depends on your provider and the update method | | DYNB_USERNAME | undefined | the requirement depends on your provider and the update method |
| DYNB_PASSWORD | undefined | the requirement depends on your provider and the update method | | DYNB_PASSWORD | undefined | the requirement depends on your provider and the update method |
| DYNB_TOKEN | undefined | the requirement depends on your provider and the update method | | DYNB_TOKEN | undefined | the requirement depends on your provider and the update method |
@@ -154,4 +154,4 @@ services:
| DYNB_DEBUG | undefined | more console outputs | | DYNB_DEBUG | undefined | more console outputs |
| DYNB_IPv4_CHECK_SITE | api64.ipify.org | You need a website or Web-API that outputs your remote IP | | DYNB_IPv4_CHECK_SITE | api64.ipify.org | You need a website or Web-API that outputs your remote IP |
| DYNB_IPv6_CHECK_SITE | api64.ipify.org | You need a website or Web-API that outputs your remote IP | | DYNB_IPv6_CHECK_SITE | api64.ipify.org | You need a website or Web-API that outputs your remote IP |
| DYNB_DNS_CHECK_SERVER | 1.1.1.1 | If you are using a local DNS Resolver/Server make sure it answers with the public answer | | DYNB_DNS_CHECK_SERVER | undefined | If you are using a local DNS Resolver/Server make sure it answers with the public answer or set another server |

24
dynb-parsing-template.m4 Normal file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
# m4_ignore(
echo "This is just a script template for argbash, not the script." >&2
exit 11 #)Created by argbash-init v2.10.0
# Rearrange the order of options below according to what you would like to see in the help message.
# ARG_OPTIONAL_BOOLEAN([version],[v],[outputs the client version],[off])
# ARG_OPTIONAL_BOOLEAN([link],[l],[links to your script at ~/.local/bin/dynb],[off])
# ARG_OPTIONAL_BOOLEAN([reset],[r],[deletes the client blocking status file],[off])
# ARG_OPTIONAL_BOOLEAN([debug],[],[enables debug mode],[off])
# ARG_OPTIONAL_SINGLE([update-method],[m],[choose if you want to use DynDNS2 or the DomRobot RPC-API],[])
# ARG_OPTIONAL_SINGLE([ip-mode],[i],[updates type A (IPv4) and AAAA (IPv6) records],[])
# ARG_OPTIONAL_SINGLE([domain],[d],[set the domain you want to update],[])
# ARG_OPTIONAL_SINGLE([service-provider],[s],[set your provider in case you are using DynDNS2],[])
# ARG_OPTIONAL_SINGLE([username],[u],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([password],[p],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([token],[t],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([interval],[],[choose the seconds interval to run the script in a loop, minimum is 60],[])
# ARG_HELP([DynB - dynamic DNS update script for bash])
# ARGBASH_GO
# [ <-- needed because of Argbash
# ] <-- needed because of Argbash

297
dynb-parsing.sh Normal file
View File

@@ -0,0 +1,297 @@
#!/bin/bash
# Created by argbash-init v2.10.0
# Rearrange the order of options below according to what you would like to see in the help message.
# ARG_OPTIONAL_BOOLEAN([version],[v],[outputs the client version],[off])
# ARG_OPTIONAL_BOOLEAN([link],[l],[links to your script at ~/.local/bin/dynb],[off])
# ARG_OPTIONAL_BOOLEAN([reset],[r],[deletes the client blocking status file],[off])
# ARG_OPTIONAL_BOOLEAN([debug],[],[enables debug mode],[off])
# ARG_OPTIONAL_SINGLE([update-method],[m],[choose if you want to use DynDNS2 or the DomRobot RPC-API],[])
# ARG_OPTIONAL_SINGLE([ip-mode],[i],[updates type A (IPv4) and AAAA (IPv6) records],[])
# ARG_OPTIONAL_SINGLE([domain],[d],[set the domain you want to update],[])
# ARG_OPTIONAL_SINGLE([service-provider],[s],[set your provider in case you are using DynDNS2],[])
# ARG_OPTIONAL_SINGLE([username],[u],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([password],[p],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([token],[t],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([interval],[],[choose the seconds interval to run the script in a loop, minimum is 60],[])
# ARG_HELP([DynB - dynamic DNS update script for bash])
# ARGBASH_GO()
# needed because of Argbash --> m4_ignore([
### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.io for more info
# # When called, the process ends.
# Args:
# $1: The exit message (print to stderr)
# $2: The exit code (default is 1)
# if env var _PRINT_HELP is set to 'yes', the usage is print to stderr (prior to $1)
# Example:
# test -f "$_arg_infile" || _PRINT_HELP=yes die "Can't continue, have to supply file as an argument, got '$_arg_infile'" 4
die()
{
local _ret="${2:-1}"
test "${_PRINT_HELP:-no}" = yes && print_help >&2
echo "$1" >&2
exit "${_ret}"
}
# Function that evaluates whether a value passed to it begins by a character
# that is a short option of an argument the script knows about.
# This is required in order to support getopts-like short options grouping.
begins_with_short_option()
{
local first_option all_short_options='vlrmidsupth'
first_option="${1:0:1}"
test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}
# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_version="off"
_arg_link="off"
_arg_reset="off"
_arg_debug="off"
_arg_update_method=
_arg_ip_mode=
_arg_domain=
_arg_service_provider=
_arg_username=
_arg_password=
_arg_token=
_arg_interval=
# Function that prints general usage of the script.
# This is useful if users asks for it, or if there is an argument parsing error (unexpected / spurious arguments)
# and it makes sense to remind the user how the script is supposed to be called.
print_help()
{
printf '%s\n' "DynB - dynamic DNS update script for bash"
printf 'Usage: %s [-v|--(no-)version] [-l|--(no-)link] [-r|--(no-)reset] [--(no-)debug] [-m|--update-method <arg>] [-i|--ip-mode <arg>] [-d|--domain <arg>] [-s|--service-provider <arg>] [-u|--username <arg>] [-p|--password <arg>] [-t|--token <arg>] [--interval <arg>] [-h|--help]\n' "$0"
printf '\t%s\n' "-v, --version, --no-version: outputs the client version (off by default)"
printf '\t%s\n' "-l, --link, --no-link: links to your script at ~/.local/bin/dynb (off by default)"
printf '\t%s\n' "-r, --reset, --no-reset: deletes the client blocking status file (off by default)"
printf '\t%s\n' "--debug, --no-debug: enables debug mode (off by default)"
printf '\t%s\n' "-m, --update-method: choose if you want to use DynDNS2 or the DomRobot RPC-API (no default)"
printf '\t%s\n' "-i, --ip-mode: updates type A (IPv4) and AAAA (IPv6) records (no default)"
printf '\t%s\n' "-d, --domain: set the domain you want to update (no default)"
printf '\t%s\n' "-s, --service-provider: set your provider in case you are using DynDNS2 (no default)"
printf '\t%s\n' "-u, --username: depends on your selected update method and your provider (no default)"
printf '\t%s\n' "-p, --password: depends on your selected update method and your provider (no default)"
printf '\t%s\n' "-t, --token: depends on your selected update method and your provider (no default)"
printf '\t%s\n' "--interval: choose the seconds interval to run the script in a loop, minimum is 60 (no default)"
printf '\t%s\n' "-h, --help: Prints help"
}
# The parsing of the command-line
parse_commandline()
{
while test $# -gt 0
do
_key="$1"
case "$_key" in
# The version argurment doesn't accept a value,
# we expect the --version or -v, so we watch for them.
-v|--no-version|--version)
_arg_version="on"
test "${1:0:5}" = "--no-" && _arg_version="off"
;;
# We support getopts-style short arguments clustering,
# so as -v doesn't accept value, other short options may be appended to it, so we watch for -v*.
# After stripping the leading -v from the argument, we have to make sure
# that the first character that follows coresponds to a short option.
-v*)
_arg_version="on"
_next="${_key##-v}"
if test -n "$_next" -a "$_next" != "$_key"
then
{ begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
fi
;;
# See the comment of option '--version' to see what's going on here - principle is the same.
-l|--no-link|--link)
_arg_link="on"
test "${1:0:5}" = "--no-" && _arg_link="off"
;;
# See the comment of option '-v' to see what's going on here - principle is the same.
-l*)
_arg_link="on"
_next="${_key##-l}"
if test -n "$_next" -a "$_next" != "$_key"
then
{ begins_with_short_option "$_next" && shift && set -- "-l" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
fi
;;
# See the comment of option '--version' to see what's going on here - principle is the same.
-r|--no-reset|--reset)
_arg_reset="on"
test "${1:0:5}" = "--no-" && _arg_reset="off"
;;
# See the comment of option '-v' to see what's going on here - principle is the same.
-r*)
_arg_reset="on"
_next="${_key##-r}"
if test -n "$_next" -a "$_next" != "$_key"
then
{ begins_with_short_option "$_next" && shift && set -- "-r" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
fi
;;
# See the comment of option '--version' to see what's going on here - principle is the same.
--no-debug|--debug)
_arg_debug="on"
test "${1:0:5}" = "--no-" && _arg_debug="off"
;;
# We support whitespace as a delimiter between option argument and its value.
# Therefore, we expect the --update-method or -m value.
# so we watch for --update-method and -m.
# Since we know that we got the long or short option,
# we just reach out for the next argument to get the value.
-m|--update-method)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_update_method="$2"
shift
;;
# We support the = as a delimiter between option argument and its value.
# Therefore, we expect --update-method=value, so we watch for --update-method=*
# For whatever we get, we strip '--update-method=' using the ${var##--update-method=} notation
# to get the argument value
--update-method=*)
_arg_update_method="${_key##--update-method=}"
;;
# We support getopts-style short arguments grouping,
# so as -m accepts value, we allow it to be appended to it, so we watch for -m*
# and we strip the leading -m from the argument string using the ${var##-m} notation.
-m*)
_arg_update_method="${_key##-m}"
;;
# See the comment of option '--update-method' to see what's going on here - principle is the same.
-i|--ip-mode)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_ip_mode="$2"
shift
;;
# See the comment of option '--update-method=' to see what's going on here - principle is the same.
--ip-mode=*)
_arg_ip_mode="${_key##--ip-mode=}"
;;
# See the comment of option '-m' to see what's going on here - principle is the same.
-i*)
_arg_ip_mode="${_key##-i}"
;;
# See the comment of option '--update-method' to see what's going on here - principle is the same.
-d|--domain)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_domain="$2"
shift
;;
# See the comment of option '--update-method=' to see what's going on here - principle is the same.
--domain=*)
_arg_domain="${_key##--domain=}"
;;
# See the comment of option '-m' to see what's going on here - principle is the same.
-d*)
_arg_domain="${_key##-d}"
;;
# See the comment of option '--update-method' to see what's going on here - principle is the same.
-s|--service-provider)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_service_provider="$2"
shift
;;
# See the comment of option '--update-method=' to see what's going on here - principle is the same.
--service-provider=*)
_arg_service_provider="${_key##--service-provider=}"
;;
# See the comment of option '-m' to see what's going on here - principle is the same.
-s*)
_arg_service_provider="${_key##-s}"
;;
# See the comment of option '--update-method' to see what's going on here - principle is the same.
-u|--username)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_username="$2"
shift
;;
# See the comment of option '--update-method=' to see what's going on here - principle is the same.
--username=*)
_arg_username="${_key##--username=}"
;;
# See the comment of option '-m' to see what's going on here - principle is the same.
-u*)
_arg_username="${_key##-u}"
;;
# See the comment of option '--update-method' to see what's going on here - principle is the same.
-p|--password)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_password="$2"
shift
;;
# See the comment of option '--update-method=' to see what's going on here - principle is the same.
--password=*)
_arg_password="${_key##--password=}"
;;
# See the comment of option '-m' to see what's going on here - principle is the same.
-p*)
_arg_password="${_key##-p}"
;;
# See the comment of option '--update-method' to see what's going on here - principle is the same.
-t|--token)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_token="$2"
shift
;;
# See the comment of option '--update-method=' to see what's going on here - principle is the same.
--token=*)
_arg_token="${_key##--token=}"
;;
# See the comment of option '-m' to see what's going on here - principle is the same.
-t*)
_arg_token="${_key##-t}"
;;
# See the comment of option '--update-method' to see what's going on here - principle is the same.
--interval)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_interval="$2"
shift
;;
# See the comment of option '--update-method=' to see what's going on here - principle is the same.
--interval=*)
_arg_interval="${_key##--interval=}"
;;
# See the comment of option '--version' to see what's going on here - principle is the same.
-h|--help)
print_help
exit 0
;;
# See the comment of option '-v' to see what's going on here - principle is the same.
-h*)
print_help
exit 0
;;
*)
_PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
;;
esac
shift
done
}
# Now call all the functions defined above that are needed to get the job done
parse_commandline "$@"
# OTHER STUFF GENERATED BY Argbash
### END OF CODE GENERATED BY Argbash (sortof) ### ])
# [ <-- needed because of Argbash
# vvv PLACE YOUR CODE HERE vvv
# PUT YOUR CODE HERE
# ^^^ TERMINATE YOUR CODE BEFORE THE BOTTOM ARGBASH MARKER ^^^
# ] <-- needed because of Argbash

612
dynb.sh
View File

@@ -41,7 +41,7 @@ _ipv4_checker=api64.ipify.org
_ipv6_checker=api64.ipify.org _ipv6_checker=api64.ipify.org
## An exernal DNS check server prevents wrong info from local DNS servers/resolvers ## An exernal DNS check server prevents wrong info from local DNS servers/resolvers
_DNS_checkServer=1.1.1.1 _DNS_checkServer=
## if you are actively using multiple network interfaces you might want to specify this ## if you are actively using multiple network interfaces you might want to specify this
## normally the default value is okay ## normally the default value is okay
@@ -73,262 +73,6 @@ _debug=0
_minimum_looptime=60 _minimum_looptime=60
_loopMode=0 _loopMode=0
# Created by argbash-init v2.10.0
# Rearrange the order of options below according to what you would like to see in the help message.
# ARG_OPTIONAL_BOOLEAN([version],[v],[outputs the client version],[off])
# ARG_OPTIONAL_BOOLEAN([link],[l],[links to your script at ~/.local/bin/dynb],[off])
# ARG_OPTIONAL_BOOLEAN([reset],[r],[deletes the client blocking status file],[off])
# ARG_OPTIONAL_BOOLEAN([debug],[],[enables debug mode],[off])
# ARG_OPTIONAL_SINGLE([update-method],[m],[choose if you want to use DynDNS2 or the DomRobot RPC-API],[])
# ARG_OPTIONAL_SINGLE([ip-mode],[i],[updates type A (IPv4) and AAAA (IPv6) records],[])
# ARG_OPTIONAL_SINGLE([domain],[d],[set the domain you want to update],[])
# ARG_OPTIONAL_SINGLE([service-provider],[s],[set your provider in case you are using DynDNS2],[])
# ARG_OPTIONAL_SINGLE([username],[u],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([password],[p],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([token],[t],[depends on your selected update method and your provider],[])
# ARG_OPTIONAL_SINGLE([interval],[],[choose the seconds interval to run the script in a loop, minimum is 60],[])
# ARG_HELP([DynB - dynamic DNS update script for bash])
# ARGBASH_GO()
# needed because of Argbash --> m4_ignore([
### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.io for more info
die()
{
local _ret="${2:-1}"
test "${_PRINT_HELP:-no}" = yes && print_help >&2
echo "$1" >&2
exit "${_ret}"
}
begins_with_short_option()
{
local first_option all_short_options='vlrmidsupth'
first_option="${1:0:1}"
test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}
# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_version="off"
_arg_link="off"
_arg_reset="off"
_arg_debug="off"
_arg_update_method=
_arg_ip_mode=
_arg_domain=
_arg_service_provider=
_arg_username=
_arg_password=
_arg_token=
_arg_interval=
print_help()
{
printf '%s\n' "DynB - dynamic DNS update script for bash"
printf 'Usage: %s [-v|--(no-)version] [-l|--(no-)link] [-r|--(no-)reset] [--(no-)debug] [-m|--update-method <arg>] [-i|--ip-mode <arg>] [-d|--domain <arg>] [-s|--service-provider <arg>] [-u|--username <arg>] [-p|--password <arg>] [-t|--token <arg>] [--interval <arg>] [-h|--help]\n' "$0"
printf '\t%s\n' "-v, --version, --no-version: outputs the client version (off by default)"
printf '\t%s\n' "-l, --link, --no-link: links to your script at ~/.local/bin/dynb (off by default)"
printf '\t%s\n' "-r, --reset, --no-reset: deletes the client blocking status file (off by default)"
printf '\t%s\n' "--debug, --no-debug: enables debug mode (off by default)"
printf '\t%s\n' "-m, --update-method: choose if you want to use DynDNS2 or the DomRobot RPC-API (no default)"
printf '\t%s\n' "-i, --ip-mode: updates type A (IPv4) and AAAA (IPv6) records (no default)"
printf '\t%s\n' "-d, --domain: set the domain you want to update (no default)"
printf '\t%s\n' "-s, --service-provider: set your provider in case you are using DynDNS2 (no default)"
printf '\t%s\n' "-u, --username: depends on your selected update method and your provider (no default)"
printf '\t%s\n' "-p, --password: depends on your selected update method and your provider (no default)"
printf '\t%s\n' "-t, --token: depends on your selected update method and your provider (no default)"
printf '\t%s\n' "--interval: choose the seconds interval to run the script in a loop, minimum is 60 (no default)"
printf '\t%s\n' "-h, --help: Prints help"
}
parse_commandline()
{
while test $# -gt 0
do
_key="$1"
case "$_key" in
-v|--no-version|--version)
_arg_version="on"
test "${1:0:5}" = "--no-" && _arg_version="off"
;;
-v*)
_arg_version="on"
_next="${_key##-v}"
if test -n "$_next" -a "$_next" != "$_key"
then
{ begins_with_short_option "$_next" && shift && set -- "-v" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
fi
;;
-l|--no-link|--link)
_arg_link="on"
test "${1:0:5}" = "--no-" && _arg_link="off"
;;
-l*)
_arg_link="on"
_next="${_key##-l}"
if test -n "$_next" -a "$_next" != "$_key"
then
{ begins_with_short_option "$_next" && shift && set -- "-l" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
fi
;;
-r|--no-reset|--reset)
_arg_reset="on"
test "${1:0:5}" = "--no-" && _arg_reset="off"
;;
-r*)
_arg_reset="on"
_next="${_key##-r}"
if test -n "$_next" -a "$_next" != "$_key"
then
{ begins_with_short_option "$_next" && shift && set -- "-r" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option."
fi
;;
--no-debug|--debug)
_arg_debug="on"
test "${1:0:5}" = "--no-" && _arg_debug="off"
;;
-m|--update-method)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_update_method="$2"
shift
;;
--update-method=*)
_arg_update_method="${_key##--update-method=}"
;;
-m*)
_arg_update_method="${_key##-m}"
;;
-i|--ip-mode)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_ip_mode="$2"
shift
;;
--ip-mode=*)
_arg_ip_mode="${_key##--ip-mode=}"
;;
-i*)
_arg_ip_mode="${_key##-i}"
;;
-d|--domain)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_domain="$2"
shift
;;
--domain=*)
_arg_domain="${_key##--domain=}"
;;
-d*)
_arg_domain="${_key##-d}"
;;
-s|--service-provider)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_service_provider="$2"
shift
;;
--service-provider=*)
_arg_service_provider="${_key##--service-provider=}"
;;
-s*)
_arg_service_provider="${_key##-s}"
;;
-u|--username)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_username="$2"
shift
;;
--username=*)
_arg_username="${_key##--username=}"
;;
-u*)
_arg_username="${_key##-u}"
;;
-p|--password)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_password="$2"
shift
;;
--password=*)
_arg_password="${_key##--password=}"
;;
-p*)
_arg_password="${_key##-p}"
;;
-t|--token)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_token="$2"
shift
;;
--token=*)
_arg_token="${_key##--token=}"
;;
-t*)
_arg_token="${_key##-t}"
;;
--interval)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_interval="$2"
shift
;;
--interval=*)
_arg_interval="${_key##--interval=}"
;;
-h|--help)
print_help
exit 0
;;
-h*)
print_help
exit 0
;;
*)
_PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
;;
esac
shift
done
}
parse_commandline "$@"
# OTHER STUFF GENERATED BY Argbash
### END OF CODE GENERATED BY Argbash (sortof) ### ])
# [ <-- needed because of Argbash
# The generated argbash help message does not look as nice as this:
_help_message="$(cat << 'EOF'
dynb - dynamic DNS update script for bash
Usage
=====
dynb [options]
-h, --help displays this help message
--version outputs the client version
--link links to your script at ~/.local/bin/dynb
--reset deletes the client blocking status file
Configuration options
---------------------
-i | --ip-mode [ 4 | 6 | dual ] updates type A (IPv4) and AAAA (IPv6) records
-m | --update-method [dyndns | domrobot] choose if you want to use DynDNS2 or the DomRobot RPC-API
-s | --service-provider inwx set your provider in case you are using DynDNS2
-d | --domain "dyndns.example.com" set the domain you want to update
-u | --username "user42" depends on your selected update method and your provider
-p | --password "SuperSecretPassword" depends on your selected update method and your provider
-t | --token "YourProviderGivenToken" depends on your selected update method and your provider
##### examples #####
dynb --ip-mode dual --update-method domrobot --domain dyndns.example.com --username user42 --password SuperSecretPassword
dynb --ip-mode dual --update-method dyndns --service-provider inwx --domain dyndns.example.com --username user42 --password SuperSecretPassword
EOF
)"
function loopMode() { function loopMode() {
if [[ $_loopMode -eq 1 ]]; then if [[ $_loopMode -eq 1 ]]; then
return 0 return 0
@@ -364,40 +108,44 @@ function logtime() {
# The main domain as an identifier for the dns zone is required for the updateRecord call # The main domain as an identifier for the dns zone is required for the updateRecord call
function getMainDomain() { function getMainDomain() {
request=$( echo "{}" | \ request=$(
jq '(.method="nameserver.list")' | \ echo "{}" |
jq "(.params.user=\"$DYNB_USERNAME\")" | \ jq '(.method="nameserver.list")' |
jq "(.params.user=\"$DYNB_USERNAME\")" |
jq "(.params.pass=\"$DYNB_PASSWORD\")" jq "(.params.pass=\"$DYNB_PASSWORD\")"
) )
_response=$(curl --silent \ _response=$(
curl --silent \
"$_interface_str" \ "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
--header "Content-Type: application/json" \ --header "Content-Type: application/json" \
--request POST $_INWX_JSON_API_URL \ --request POST $_INWX_JSON_API_URL \
--data "$request" | jq ".resData.domains[] | select(inside(.domain=\"$DYNB_DYN_DOMAIN\"))" --data "$request" | jq ".resData.domains[] | select(inside(.domain=\"$DYNB_DYN_DOMAIN\"))"
) )
_main_domain=$( echo "$_response" | jq --raw-output '.domain' ) _main_domain=$(echo "$_response" | jq --raw-output '.domain')
} }
function fetchDNSRecords() { function fetchDNSRecords() {
request=$( echo "{}" | \ request=$(
jq '(.method="'nameserver.info'")' | \ echo "{}" |
jq "(.params.user=\"$DYNB_USERNAME\")" | \ jq '(.method="'nameserver.info'")' |
jq "(.params.pass=\"$DYNB_PASSWORD\")" | \ jq "(.params.user=\"$DYNB_USERNAME\")" |
jq "(.params.domain=\"$_main_domain\")" | \ jq "(.params.pass=\"$DYNB_PASSWORD\")" |
jq "(.params.domain=\"$_main_domain\")" |
jq "(.params.name=\"$DYNB_DYN_DOMAIN\")" jq "(.params.name=\"$DYNB_DYN_DOMAIN\")"
) )
_response=$( curl --silent \ _response=$(
curl --silent \
"$_interface_str" \ "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
--header "Content-Type: application/json" \ --header "Content-Type: application/json" \
--request POST $_INWX_JSON_API_URL \ --request POST $_INWX_JSON_API_URL \
--data "$request" --data "$request"
) )
_dns_records=$( echo "$_response" | jq '.resData.record[]' ) _dns_records=$(echo "$_response" | jq '.resData.record[]')
} }
# requires parameter A or AAAA # requires parameter A or AAAA
@@ -417,8 +165,18 @@ function getDNSIP() {
# 2. param: IP check server address # 2. param: IP check server address
# result to stdout # result to stdout
function getRemoteIP() { function getRemoteIP() {
curl --silent "$_interface_str" --user-agent "$_userAgent" \ if [[ -n $_DNS_checkServer ]]; then
--ipv"${1}" --dns-servers 1.1.1.1 --location "${2}" curl --silent "$_interface_str" --user-agent "$_userAgent" \
--ipv"${1}" --dns-servers "$_DNS_checkServer" --location "${2}"
else
curl --silent "$_interface_str" --user-agent "$_userAgent" \
--ipv"${1}" --location "${2}"
fi
# shellcheck disable=2181
if [[ $? -gt 0 ]]; then
errorMessage "IPCheck (getRemoteIP ${1}) request failed"
exit 1
fi
} }
# requires parameter # requires parameter
@@ -433,23 +191,25 @@ function updateRecord() {
IP=$_new_IPv6 IP=$_new_IPv6
fi fi
if [[ $IP != "" ]]; then if [[ $IP != "" ]]; then
request=$( echo "{}" | \ request=$(
jq '(.method="nameserver.updateRecord")' | \ echo "{}" |
jq "(.params.user=\"$DYNB_USERNAME\")" | \ jq '(.method="nameserver.updateRecord")' |
jq "(.params.pass=\"$DYNB_PASSWORD\")" | \ jq "(.params.user=\"$DYNB_USERNAME\")" |
jq "(.params.id=\"$ID\")" | \ jq "(.params.pass=\"$DYNB_PASSWORD\")" |
jq "(.params.content=\"$IP\")" | \ jq "(.params.id=\"$ID\")" |
jq "(.params.ttl=\"$TTL\")" jq "(.params.content=\"$IP\")" |
jq "(.params.ttl=\"$TTL\")"
) )
_response=$(curl --silent \ _response=$(
"$_interface_str" \ curl --silent \
--user-agent "$_userAgent" \ "$_interface_str" \
--header "Content-Type: application/json" \ --user-agent "$_userAgent" \
--request POST $_INWX_JSON_API_URL \ --header "Content-Type: application/json" \
--data "$request" --request POST $_INWX_JSON_API_URL \
) --data "$request"
echo -e "$(echo "$_response" | jq --raw-output '.msg')\n Domain: $DYNB_DYN_DOMAIN\n new IPv${1}: $IP" )
echo -e "$(echo "$_response" | jq --raw-output '.msg')\n Domain: $DYNB_DYN_DOMAIN\n new IPv${1}: $IP"
fi fi
} }
@@ -465,26 +225,26 @@ function dynupdate() {
DYNV6_DYNDNS_UPDATE_URL="https://dynv6.com/api/update?zone=$DYNB_DYN_DOMAIN&token=$DYNB_TOKEN&" DYNV6_DYNDNS_UPDATE_URL="https://dynv6.com/api/update?zone=$DYNB_DYN_DOMAIN&token=$DYNB_TOKEN&"
case $DYNB_SERVICE_PROVIDER in case $DYNB_SERVICE_PROVIDER in
inwx* | INWX* ) inwx* | INWX*)
dyndns_update_url=$INWX_DYNDNS_UPDATE_URL dyndns_update_url=$INWX_DYNDNS_UPDATE_URL
;; ;;
deSEC* | desec* | dedyn* ) deSEC* | desec* | dedyn*)
dyndns_update_url="${DESEC_DYNDNS_UPDATE_URL}" dyndns_update_url="${DESEC_DYNDNS_UPDATE_URL}"
;; ;;
dynv6* ) dynv6*)
dyndns_update_url="${DYNV6_DYNDNS_UPDATE_URL}" dyndns_update_url="${DYNV6_DYNDNS_UPDATE_URL}"
myip_str=ipv4 myip_str=ipv4
myipv6_str=ipv6 myipv6_str=ipv6
;; ;;
DuckDNS* | duckdns* ) DuckDNS* | duckdns*)
dyndns_update_url="${DUCKDNS_DYNDNS_UPDATE_URL}" dyndns_update_url="${DUCKDNS_DYNDNS_UPDATE_URL}"
myip_str=ipv4 myip_str=ipv4
myipv6_str=ipv6 myipv6_str=ipv6
;; ;;
* ) *)
errorMessage "$DYNB_SERVICE_PROVIDER is not supported" errorMessage "$DYNB_SERVICE_PROVIDER is not supported"
exit 1 exit 1
;; ;;
esac esac
# pre encode ip parameters # pre encode ip parameters
@@ -501,29 +261,30 @@ function dynupdate() {
## request ## ## request ##
case $DYNB_SERVICE_PROVIDER in case $DYNB_SERVICE_PROVIDER in
inwx* | INWX* ) inwx* | INWX*)
_response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
--user "$DYNB_USERNAME":"$DYNB_PASSWORD" \
"${dyndns_update_url}" )
;;
deSEC* | desec* | dedyn* )
_response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
--header "Authorization: Token $DYNB_TOKEN" \
--get --data-urlencode "hostname=$DYNB_DYN_DOMAIN" \
"${dyndns_update_url}" )
;;
dynv6* | duckDNS* | duckdns* )
_response=$(curl --silent "$_interface_str" \ _response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
"${dyndns_update_url}" --user "$DYNB_USERNAME":"$DYNB_PASSWORD" \
"${dyndns_update_url}")
;;
deSEC* | desec* | dedyn*)
_response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
--header "Authorization: Token $DYNB_TOKEN" \
--get --data-urlencode "hostname=$DYNB_DYN_DOMAIN" \
"${dyndns_update_url}")
;;
dynv6* | duckDNS* | duckdns*)
_response=$(
curl --silent "$_interface_str" \
--user-agent "$_userAgent" \
"${dyndns_update_url}"
) )
;; ;;
esac esac
case $_response in case $_response in
good* | OK* | "addresses updated" ) good* | OK* | "addresses updated")
if [[ $_response == "good 127.0.0.1" ]]; then if [[ $_response == "good 127.0.0.1" ]]; then
errorMessage "$_response: Request ignored." errorMessage "$_response: Request ignored."
return 1 return 1
@@ -532,52 +293,52 @@ function dynupdate() {
_errorCounter=0 _errorCounter=0
return 0 return 0
fi fi
;; ;;
nochg* ) nochg*)
infoMessage "$_response: Nothing has changed, IP addresses are still up to date." infoMessage "$_response: Nothing has changed, IP addresses are still up to date."
return 1 return 1
;; ;;
abuse ) abuse)
errorMessage "$_response: Username is blocked due to abuse." errorMessage "$_response: Username is blocked due to abuse."
return 1 return 1
;; ;;
badauth | 401 ) badauth | 401)
errorMessage "$_response: Invalid username password combination." errorMessage "$_response: Invalid username password combination."
return 1 return 1
;; ;;
badagent ) badagent)
errorMessage "$_response: Client disabled. Something is very wrong!" errorMessage "$_response: Client disabled. Something is very wrong!"
return 1 return 1
;; ;;
!donator ) !donator)
errorMessage "$_response: An update request was sent, including a feature that is not available to that particular user such as offline options." errorMessage "$_response: An update request was sent, including a feature that is not available to that particular user such as offline options."
return 1 return 1
;; ;;
!yours ) !yours)
errorMessage "$_response: The domain does not belong to your user account" errorMessage "$_response: The domain does not belong to your user account"
return 1 return 1
;; ;;
notfqdn ) notfqdn)
errorMessage "$_response: Hostname $DYNB_DYN_DOMAIN is invalid" errorMessage "$_response: Hostname $DYNB_DYN_DOMAIN is invalid"
return 1 return 1
;; ;;
nohost ) nohost)
errorMessage "$_response: Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request." errorMessage "$_response: Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request."
return 1 return 1
;; ;;
numhost ) numhost)
errorMessage "$_response: Too many hostnames have been specified for this update" errorMessage "$_response: Too many hostnames have been specified for this update"
return 1 return 1
;; ;;
dnserr ) dnserr)
errorMessage "$_response: There is an internal error in the dyndns update system. Retry update no sooner than 30 minutes." errorMessage "$_response: There is an internal error in the dyndns update system. Retry update no sooner than 30 minutes."
return 1 return 1
;; ;;
911 | 5* ) 911 | 5*)
errorMessage "$_response: A fatal error on provider side such as a database outage. Retry update no sooner than 30 minutes." errorMessage "$_response: A fatal error on provider side such as a database outage. Retry update no sooner than 30 minutes."
return 1 return 1
;; ;;
* ) *)
if [[ "$_response" == "$_status" ]]; then if [[ "$_response" == "$_status" ]]; then
errorMessage "An unknown response code has been received. $_response" errorMessage "An unknown response code has been received. $_response"
return 1 return 1
@@ -585,34 +346,34 @@ function dynupdate() {
errorMessage "unknown respnse code: $_response" errorMessage "unknown respnse code: $_response"
return 0 return 0
fi fi
;; ;;
esac esac
} }
function setStatus() { function setStatus() {
echo "_status=$1; _eventTime=$2; _errorCounter=$3; _statusHostname=$4; _statusUsername=$5; _statusPassword=$6" > /tmp/dynb.status echo "_status=$1; _eventTime=$2; _errorCounter=$3; _statusHostname=$4; _statusUsername=$5; _statusPassword=$6" >/tmp/dynb.status
} }
# handle errors from past update requests # handle errors from past update requests
function checkStatus() { function checkStatus() {
case $_status in case $_status in
nochg* ) nochg*)
if [[ _errorCounter -gt 1 ]]; then if [[ _errorCounter -gt 1 ]]; then
errorMessage "The update client was spamming unnecessary update requests, something might be wrong with your IP-Check site." errorMessage "The update client was spamming unnecessary update requests, something might be wrong with your IP-Check site."
errorMessage "Fix your config an then delete $_statusFile or restart your docker container" errorMessage "Fix your config an then delete $_statusFile or restart your docker container"
return 1 return 1
fi fi
;; ;;
nohost | !yours ) nohost | !yours)
if [[ "$_statusHostname" == "$DYNB_DYN_DOMAIN" && ( "$_statusUsername" == "$DYNB_USERNAME" || $_statusUsername == "$DYNB_TOKEN" ) ]]; then if [[ "$_statusHostname" == "$DYNB_DYN_DOMAIN" && ("$_statusUsername" == "$DYNB_USERNAME" || $_statusUsername == "$DYNB_TOKEN") ]]; then
errorMessage "Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request." errorMessage "Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request."
return 1 return 1
else else
rm "$_statusFile" rm "$_statusFile"
fi fi
return 0 return 0
;; ;;
badauth | 401 ) badauth | 401)
if [[ "$_statusUsername" == "$DYNB_USERNAME" && "$_statusPassword" == "$DYNB_PASSWORD" ]]; then if [[ "$_statusUsername" == "$DYNB_USERNAME" && "$_statusPassword" == "$DYNB_PASSWORD" ]]; then
errorMessage "Invalid username password combination." errorMessage "Invalid username password combination."
return 1 return 1
@@ -620,27 +381,27 @@ function checkStatus() {
rm "$_statusFile" rm "$_statusFile"
fi fi
return 0 return 0
;; ;;
badagent ) badagent)
errorMessage "Client is deactivated by provider." errorMessage "Client is deactivated by provider."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade." echo "Fix your config and then manually remove $_statusFile to reset the client blockade."
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
!donator ) !donator)
errorMessage "An update request was sent, including a feature that is not available to that particular user such as offline options." errorMessage "An update request was sent, including a feature that is not available to that particular user such as offline options."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade" echo "Fix your config and then manually remove $_statusFile to reset the client blockade"
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
abuse ) abuse)
errorMessage "Username is blocked due to abuse." errorMessage "Username is blocked due to abuse."
echo "Fix your config and then manually remove $_statusFile to reset the client blockade" echo "Fix your config and then manually remove $_statusFile to reset the client blockade"
echo "If it still fails file an issue at github or try another client :)" echo "If it still fails file an issue at github or try another client :)"
return 1 return 1
;; ;;
911 | 5* ) 911 | 5*)
delta=$(( $(date +%s) - _eventTime )) delta=$(($(date +%s) - _eventTime))
if [[ $delta -lt 1800 ]]; then if [[ $delta -lt 1800 ]]; then
errorMessage "$_status: The provider currently has an fatal error. DynB will wait for next update until 30 minutes have passed since last request, $(date --date=@$delta -u +%M) minutes already passed." errorMessage "$_status: The provider currently has an fatal error. DynB will wait for next update until 30 minutes have passed since last request, $(date --date=@$delta -u +%M) minutes already passed."
return 1 return 1
@@ -648,67 +409,63 @@ function checkStatus() {
rm "$_statusFile" rm "$_statusFile"
fi fi
return 0 return 0
;; ;;
* ) *)
if [[ _errorCounter -gt 1 ]]; then if [[ _errorCounter -gt 1 ]]; then
errorMessage "An unknown response code has repeatedly been received. $_response" errorMessage "An unknown response code has repeatedly been received. $_response"
return 1 return 1
else else
return 0 return 0
fi fi
;; ;;
esac esac
} }
# requires parameter # requires parameter
# 1. param: 4 or 6 for IP version # 1. param: 4 or 6 for IP version
function ipHasChanged() { function ipHasChanged() {
if [[ ${1} == 4 ]]; then case ${1} in
remote_ip=$(getRemoteIP 4 $_ipv4_checker) 4)
#TODO: this is duplicated code, refactor this. remote_ip=$(getRemoteIP 4 $_ipv4_checker)
if [[ $? -gt 0 ]]; then if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then
errorMessage "IPCheck (getRemoteIP 4) request failed $remote_ip" dns_ip=$(getDNSIP A)
return 0 else
fi if [[ -n $_DNS_checkServer ]]; then
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then dig_response=$(dig @"${_DNS_checkServer}" in a +short "$DYNB_DYN_DOMAIN")
dns_ip=$(getDNSIP A) else
else dig_response=$(dig in a +short "$DYNB_DYN_DOMAIN")
dig_response=$(dig @${_DNS_checkServer} in a +short "$DYNB_DYN_DOMAIN") fi
#TODO: this is duplicated code, refactor this. if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then
if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then errorMessage "DNS request failed $dig_response"
errorMessage "DNS request failed $dig_response" return 0
return 0 fi
dns_ip=$dig_response
fi fi
dns_ip=$dig_response _new_IPv4=$remote_ip
fi debugMessage "New IPv4: $_new_IPv4 old was: $dns_ip"
fi ;;
if [[ ${1} == 6 ]]; then 6)
remote_ip=$(getRemoteIP 6 $_ipv6_checker) remote_ip=$(getRemoteIP 6 $_ipv6_checker)
#TODO: this is duplicated code, refactor this. if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then
if [[ $? -gt 0 ]]; then dns_ip=$(getDNSIP AAAA)
errorMessage "IPCheck (getRemoteIP 6) request failed $remote_ip" else
return 0 if [[ -n $_DNS_checkServer ]]; then
fi dig_response=$(dig @"${_DNS_checkServer}" in aaaa +short "$DYNB_DYN_DOMAIN")
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then else
dns_ip=$(getDNSIP AAAA) dig_response=$(dig in aaaa +short "$DYNB_DYN_DOMAIN")
else fi
dig_response=$(dig @${_DNS_checkServer} in aaaa +short "$DYNB_DYN_DOMAIN") if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then
#TODO: this is duplicated code, refactor this. errorMessage "DNS request failed $dig_response"
if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then return 0
errorMessage "DNS request failed $dig_response" fi
return 0 dns_ip=$dig_response
fi fi
dns_ip=$dig_response _new_IPv6=$remote_ip
fi debugMessage "New IPv6: $_new_IPv6 old was: $dns_ip"
fi ;;
*) ;;
if [[ ${1} == 4 ]]; then esac
_new_IPv4=$remote_ip
debugMessage "New IPv4: $_new_IPv4 old was: $dns_ip"
else
_new_IPv6=$remote_ip
debugMessage "New IPv6: $_new_IPv6 old was: $dns_ip"
fi
if [[ "$remote_ip" == "$dns_ip" ]]; then if [[ "$remote_ip" == "$dns_ip" ]]; then
return 0 return 0
@@ -722,42 +479,54 @@ function ipHasChanged() {
################ ################
function handleParameters() { function handleParameters() {
# shellcheck disable=SC2154
if [[ $_arg_version == "on" ]]; then if [[ $_arg_version == "on" ]]; then
echo $_version echo $_version
exit 0 exit 0
fi fi
# shellcheck disable=SC2154
if [[ $_arg_link == "on" ]]; then if [[ $_arg_link == "on" ]]; then
ln --verbose --symbolic "$(realpath "$0")" "$HOME/.local/bin/dynb" ln --verbose --symbolic "$(realpath "$0")" "$HOME/.local/bin/dynb"
exit 0 exit 0
fi fi
# shellcheck disable=SC2154
if [[ $_arg_reset == "on" ]]; then if [[ $_arg_reset == "on" ]]; then
rm --verbose "$_statusFile" rm --verbose "$_statusFile"
exit 0 exit 0
fi fi
if [[ $_arg_debug == "on" ]]; then # shellcheck disable=SC2154
if [[ $_arg_debug == "on" ]]; then
_debug=1 _debug=1
fi fi
# shellcheck disable=SC2154
if [[ $_arg_update_method != "" ]]; then if [[ $_arg_update_method != "" ]]; then
DYNB_UPDATE_METHOD=$_arg_update_method DYNB_UPDATE_METHOD=$_arg_update_method
fi fi
# shellcheck disable=SC2154
if [[ $_arg_ip_mode != "" ]]; then if [[ $_arg_ip_mode != "" ]]; then
DYNB_IP_MODE=$_arg_ip_mode DYNB_IP_MODE=$_arg_ip_mode
fi fi
# shellcheck disable=SC2154
if [[ $_arg_domain != "" ]]; then if [[ $_arg_domain != "" ]]; then
DYNB_DYN_DOMAIN=$_arg_domain DYNB_DYN_DOMAIN=$_arg_domain
fi fi
# shellcheck disable=SC2154
if [[ $_arg_service_provider != "" ]]; then if [[ $_arg_service_provider != "" ]]; then
DYNB_SERVICE_PROVIDER=$_arg_service_provider DYNB_SERVICE_PROVIDER=$_arg_service_provider
fi fi
# shellcheck disable=SC2154
if [[ $_arg_username != "" ]]; then if [[ $_arg_username != "" ]]; then
DYNB_USERNAME=$_arg_username DYNB_USERNAME=$_arg_username
fi fi
# shellcheck disable=SC2154
if [[ $_arg_password != "" ]]; then if [[ $_arg_password != "" ]]; then
DYNB_PASSWORD=$_arg_password DYNB_PASSWORD=$_arg_password
fi fi
# shellcheck disable=SC2154
if [[ $_arg_token != "" ]]; then if [[ $_arg_token != "" ]]; then
DYNB_TOKEN=$_arg_token DYNB_TOKEN=$_arg_token
fi fi
# shellcheck disable=SC2154
if [[ $_arg_interval != "" ]]; then if [[ $_arg_interval != "" ]]; then
DYNB_INTERVAL=$_arg_interval DYNB_INTERVAL=$_arg_interval
fi fi
@@ -770,7 +539,7 @@ function handleParameters() {
else else
_loopMode=1 _loopMode=1
fi fi
if [[ $_network_interface != "" ]]; then if [[ $_network_interface != "" ]]; then
_interface_str="--interface $_network_interface" _interface_str="--interface $_network_interface"
fi fi
@@ -788,9 +557,11 @@ function handleParameters() {
if [[ $DYNB_DEBUG == true ]]; then if [[ $DYNB_DEBUG == true ]]; then
_debug=1 _debug=1
fi fi
# shellcheck disable=SC2154
if [[ -n $DYNB_IPv4_CHECK_SITE ]]; then if [[ -n $DYNB_IPv4_CHECK_SITE ]]; then
_ipv4_checker=$DYNB_IPv4_CHECK_SITE _ipv4_checker=$DYNB_IPv4_CHECK_SITE
fi fi
# shellcheck disable=SC2154
if [[ -n $DYNB_IPv6_CHECK_SITE ]]; then if [[ -n $DYNB_IPv6_CHECK_SITE ]]; then
_ipv6_checker=$DYNB_IPv6_CHECK_SITE _ipv6_checker=$DYNB_IPv6_CHECK_SITE
fi fi
@@ -809,13 +580,13 @@ function checkDependencies() {
for i in curl dig; do for i in curl dig; do
if ! command -v $i >/dev/null 2>&1; then if ! command -v $i >/dev/null 2>&1; then
errorMessage "could not find \"$i\", DynB depends on it. " errorMessage "could not find \"$i\", DynB depends on it. "
(( failCounter++ )) ((failCounter++))
fi fi
done done
[[ -x $(command -v jq 2> /dev/null) ]] || { [[ -x $(command -v jq 2>/dev/null) ]] || {
if [[ $DYNB_UPDATE_METHOD != dyndns* ]]; then if [[ $DYNB_UPDATE_METHOD != dyndns* ]]; then
echo "This script depends on jq and it is not available." >&2 echo "This script depends on jq and it is not available." >&2
(( failCounter++ )) ((failCounter++))
fi fi
} }
if [[ failCounter -gt 0 ]]; then if [[ failCounter -gt 0 ]]; then
@@ -876,11 +647,11 @@ function doDynDNS2Updates() {
changed=0 changed=0
if [[ $_is_IPv4_enabled == true ]]; then if [[ $_is_IPv4_enabled == true ]]; then
ipHasChanged 4 ipHasChanged 4
(( changed += $? )) ((changed += $?))
fi fi
if [[ $_is_IPv6_enabled == true ]]; then if [[ $_is_IPv6_enabled == true ]]; then
ipHasChanged 6 ipHasChanged 6
(( changed += $? )) ((changed += $?))
fi fi
if [[ $changed -gt 0 ]]; then if [[ $changed -gt 0 ]]; then
if checkStatus; then if checkStatus; then
@@ -889,7 +660,7 @@ function doDynDNS2Updates() {
debugMessage "DynDNS2 update success" debugMessage "DynDNS2 update success"
else else
debugMessage "Save new status after dynupdate has failed" debugMessage "Save new status after dynupdate has failed"
setStatus "$_response" "$(date +%s)" $(( _errorCounter += 1 )) "$DYNB_DYN_DOMAIN" "${DYNB_USERNAME}" "${DYNB_PASSWORD}${DYNB_TOKEN}" setStatus "$_response" "$(date +%s)" $((_errorCounter += 1)) "$DYNB_DYN_DOMAIN" "${DYNB_USERNAME}" "${DYNB_PASSWORD}${DYNB_TOKEN}"
fi fi
else else
debugMessage "Skip DynDNS2 update, checkStatus fetched previous error." debugMessage "Skip DynDNS2 update, checkStatus fetched previous error."
@@ -913,8 +684,8 @@ function doUpdates() {
## MAIN method ## ## MAIN method ##
################# #################
function dynb() { function dynb() {
## parameters and checks # shellcheck disable=SC1091,SC1090
checkDependencies source "$(dirname "$(realpath "$0")")/dynb-parsing.sh"
# shellcheck source=.env # shellcheck source=.env
if test -f "$_configFile"; then if test -f "$_configFile"; then
@@ -933,11 +704,12 @@ function dynb() {
source "$_statusFile" source "$_statusFile"
fi fi
## parameters and checks
handleParameters handleParameters
checkDependencies
if loopMode; then if loopMode; then
while : while :; do
do
doUpdates doUpdates
sleep $DYNB_INTERVAL sleep $DYNB_INTERVAL
done done
@@ -952,7 +724,7 @@ function dynb() {
## END MAIN section ## ## END MAIN section ##
###################### ######################
dynb "${@}" dynb "${@}"
exit $? exit $?
# ] <-- needed because of Argbash # ] <-- needed because of Argbash