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

21 Commits

Author SHA1 Message Date
341d535f21 minor: 📝 update CHANGELOG 2022-06-30 13:57:27 +02:00
fc2c499daa minor: increase version 2022-06-30 13:52:48 +02:00
39d5143108 minor: lint tables in README 2022-06-30 13:51:01 +02:00
e58d87cf94 doc: 📝 update providers in README 2022-06-30 13:20:49 +02:00
9d41354695 feat: add support for ddnss.de as DynDNS2 provider 2022-06-30 09:46:40 +02:00
d8a298f58a minor: change .gitignore 2022-06-30 09:30:24 +02:00
3e89610e22 minor: response output as debug message 2022-06-30 09:30:24 +02:00
faa9c371c1 refactor: extract methods 2022-06-30 09:30:09 +02:00
11fccf2f0e minor: fix typo 2022-06-12 18:41:27 +02:00
75715cb0a8 minor: 📝 update CHANGELOG 2022-06-07 10:00:10 +02:00
6313ee4347 minor: set version 0.3.3 2022-06-07 09:58:10 +02:00
f37230401f fix: wrong parameter name for DuckDNS
Co-authored-by: Qrrbrbirlbel <Qrrbrbirlbel@users.noreply.github.com>
2022-06-06 22:26:40 +02:00
d6c98c04ad doc: 📝 add comments to docker-compose.yml example 2022-05-28 15:20:16 +02:00
64a5a76b6d minor: 📝 update CHANGELOG 2022-05-26 16:15:12 +02:00
05120c25e4 feat: add tzdata to Dockerfile for timezone config
You can now set your timezone with the environment variable
`TZ="Europe/Berlin"`
2022-05-26 16:10:47 +02:00
dcb3d7436b fix: 🐛 curl/libcurl doesn't support dns-server option
the latest alpine we are using for the docker image
does also drops the support for that option like debian/ubuntu/etc
2022-05-26 13:30:23 +02:00
fa60312c0d minor: 📝 update CHANGELOG.md 2022-05-26 10:35:03 +02:00
ba6e91bbd6 dev: 🔃 strip more prefix variants from commits for changelog 2022-05-26 10:27:03 +02:00
756c17d117 fix: abort on all dig errors 2022-04-12 20:23:52 +02:00
3d1b27aaed minor: 🎨 change code style 2022-01-31 20:40:29 +01:00
8721af229d dev: add github action with shellcheck for PRs 2021-11-05 20:58:17 +01:00
7 changed files with 430 additions and 329 deletions

View File

@@ -158,7 +158,7 @@ body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip
## ##
## Available constructs are those listed in ``body_process`` doc. ## Available constructs are those listed in ``body_process`` doc.
subject_process = (strip | subject_process = (strip |
ReSub(r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') | ReSub(r'^([cC]hg|[fF]ix|[nN]ew|[dD]oc|[fF]eat|[aA]dd|[cC]hange)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') |
SetIfEmpty("No commit message.") | ucfirst | final_dot) SetIfEmpty("No commit message.") | ucfirst | final_dot)

16
.github/workflows/shellcheck.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Run shellcheck with reviewdog
on: [pull_request]
jobs:
shellcheck:
name: runner / shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: shellcheck
uses: reviewdog/action-shellcheck@v1.9.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
path: "."
pattern: "*.sh"
exclude: "./.git/*"

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.env* .env*
docker-compose* docker-compose*
.vscode

View File

@@ -1,127 +1,156 @@
# Changelog # Changelog
## 0.3.4 (2022-06-30)
### Features
* ✨ add support for ddnss.de as DynDNS2 provider. [Eduard Veit]
### Documentation
* 📝 update providers in README. [Eduard Veit]
## 0.3.3 (2022-06-07)
### Fix
* Wrong parameter name for DuckDNS. [Eduard Veit]
### Documentation
* 📝 add comments to docker-compose.yml example. [Eduard Veit]
## 0.3.2 (2022-05-26)
### Features
* ✨ add tzdata to Dockerfile for timezone config. [Eduard Veit]
You can now set your timezone with the environment variable
`TZ="Europe/Berlin"`
## 0.3.1 (2022-05-26)
### Fix
* 🐛 curl/libcurl doesn't support dns-server option. [Eduard Veit]
the latest alpine we are using for the docker image
does also drops the support for that option like debian/ubuntu/etc
## 0.3.0 (2022-05-26)
### Features
* ✨ validate ip address respons from ip check web service. [Eduard Veit]
* ✨ check internet connection for selected ip versions. [Eduard Veit]
* 🎨 colorful info, debug and error messages. [Eduard Veit]
### Fix
* Abort on all dig errors. [Eduard Veit]
### Documentation
* 📝 add labels to Dockerfile. [Eduard Veit]
## 0.2.0 (2021-09-24) ## 0.2.0 (2021-09-24)
### New ### Features
* :sparkles: enable parameter extensions for `docker run --interactive` [Eduard Veit] * enable parameter extensions for `docker run --interactive` [Eduard Veit]
* :sparkles: add pre-commit hooks for markdown. [Eduard Veit] ### Changed
* :sparkles: change git hooks and add shfmt. [Eduard Veit] * Handle dns server selection. [Eduard Veit]
* :sparkles: add pre-commit git hook for shellcheck. [Eduard Veit]
### Changes
* :wrench: remove md-toc from pre-commit. [Eduard Veit]
* :wrench: handle dns server selection. [Eduard Veit]
### Documentation ### Documentation
* :memo: update CHANGELOG.md. [Eduard Veit] * 📝 update CHANGELOG.md. [Eduard Veit]
* :memo: document docker parameters. [Eduard Veit] * 📝 document docker parameters. [Eduard Veit]
* :memo: change default dns server setting. [Eduard Veit] * 📝 change default dns server setting. [Eduard Veit]
* :memo: update CHANGELOG. [Eduard Veit] * 📝 update CHANGELOG. [Eduard Veit]
* :memo: update README.md. [Eduard Veit] * 📝 update README.md. [Eduard Veit]
### Other
* :art: lint README.md. [Eduard Veit]
* :art: add shfmt params to pre-commit check. [Eduard Veit]
* :art: fix shell style. [Eduard Veit]
* :recycle: seperate parsing logic. [Eduard Veit]
* :recycle: normalizing pre-commit configuration to a top-level map. [Eduard Veit]
* :recycle: refactorings. [Eduard Veit]
* Refactor: :recycle: remove unused help message. [Eduard Veit]
## 0.1.2 (2021-04-23) ## 0.1.2 (2021-04-23)
### Documentation ### Documentation
* :memo: document environment variables. [Eduard Veit] * 📝 document environment variables. [Eduard Veit]
### Other
* :recycle: refactor: method extractions and other beautifications. [Eduard Veit]
## 0.1.1 (2021-04-23) ## 0.1.1 (2021-04-23)
### Fix ### Fix
* :bug: fix loop and error handling in case of connection issues. [Eduard Veit] * 🐛 fix loop and error handling in case of connection issues. [Eduard Veit]
## 0.1.0 (2021-04-22) ## 0.1.0 (2021-04-22)
### New ### Features
* :sparkles: add Dockerfile. [Eduard Veit] * add Dockerfile. [Eduard Veit]
* :sparkles: add loop mode. [Eduard Veit] * add loop mode. [Eduard Veit]
* :sparkles: add support for Duck DNS as DynDNS2 provider. [Eduard Veit] * add support for Duck DNS as DynDNS2 provider. [Eduard Veit]
* :sparkles: add support for deSEC as DynDNS2 provider. [Eduard Veit] * add support for deSEC as DynDNS2 provider. [Eduard Veit]
* :sparkles: add completion. [Eduard Veit] * add completion. [Eduard Veit]
:sparkles: add man page add man page
* :sparkles: replace getopt with argbash. [Eduard Veit] * 🔃 replace getopt with argbash. [Eduard Veit]
* :sparkles: add interpretaton of status codes and act accordingly. [Eduard Veit] * add interpretaton of status codes and act accordingly. [Eduard Veit]
* :sparkles: make network interface configurable. [Eduard Veit] * make network interface configurable. [Eduard Veit]
* :sparkles: add DynDNS2 support for dynv6.com. [Eduard Veit] * add DynDNS2 support for dynv6.com. [Eduard Veit]
* :sparkles: add .gitchangelog.rc. [Eduard Veit] ### Added
* :sparkles: add dynb.sh. [Eduard Veit] * 📝 README.md. [Eduard Veit]
* ✨ dynb.sh. [Eduard Veit]
### Changed
* 🔃 rename environment variables. [Eduard Veit]
### Fix ### Fix
* :bug: fix sourcing of config file. [Eduard Veit] * 🐛 fix error handling. [Eduard Veit]
:recycle: do some shellcheck fixes * 🐛 fix sourcing of config file. [Eduard Veit]
♻️ do some shellcheck fixes
### Documentation ### Documentation
* :memo: document example of an docker-compose.yml file. [Eduard Veit] * 📝 document example of an docker-compose.yml file. [Eduard Veit]
* :memo: document loop mode and dig as requirement. [Eduard Veit] * 📝 document `loop mode` and mention `dig` as requirement. [Eduard Veit]
* :memo: update example of .env in README.md. [Eduard Veit] * 📝 update example of .env in README.md. [Eduard Veit]
* :memo: add CHANGELOG.md. [Eduard Veit] * 📝 CHANGELOG.md. [Eduard Veit]
* :memo: add example.env. [Eduard Veit] * 📝 add example.env. [Eduard Veit]
* :memo: write README.md. [Eduard Veit]
### Other
* :recycle: refactor: rename environment variables. [Eduard Veit]
* :recycle: refactor, fix and debug error handling. [Eduard Veit]
* :recycle: refactor main code. [Eduard Veit]
* Initial commit. [EV21]

View File

@@ -7,7 +7,8 @@ apk add \
bash \ bash \
curl \ curl \
jq \ jq \
bind-tools bind-tools \
tzdata
WORKDIR /usr/src/app WORKDIR /usr/src/app

View File

@@ -7,8 +7,6 @@ IPv4 (A) and IPv6 (AAAA) record updates are supported.
<!-- TOC --> <!-- TOC -->
- [✨ Update Methods](#-update-methods) - [✨ Update Methods](#-update-methods)
- [APIs](#apis)
- [DynDNS2](#dyndns2)
- [📦 Requirements](#-requirements) - [📦 Requirements](#-requirements)
- [🚀 Installation](#-installation) - [🚀 Installation](#-installation)
- [⚙ Configuration](#-configuration) - [⚙ Configuration](#-configuration)
@@ -25,18 +23,14 @@ IPv4 (A) and IPv6 (AAAA) record updates are supported.
The following update methods are currently implemented: The following update methods are currently implemented:
### APIs | Provider | API | TTL in seconds | Credentials | own domain via NS record | free (sub-) domain |
|---------------------|-----------------------|----------------|----------------------------------------------------------------------------------------------|--------------------------|------------------------------------------------|
- INWX.com Domrobot JSON-RPC-API\ | INWX.com | Domrobot JSON-RPC-API | 300 | customer login `username` & `password`. Mobile TAN (OTP) is currently not supported by DynB. | ✔️ | ⛔ choose one of your owned domains |
Limitations: | INWX.com | DynDNS2 | 60 | specific dyndns `username` & `password` | ✔️ | ⛔ choose one of your owned domains per account |
- minimum TTL is 300 (5 minutes) | deSEC.io (dedyn.io) | DynDNS2 | 60 | `token` | ✔️ | ✔️ |
| DuckDNS.org | DynDNS2 | 60 | `token` | ⛔ | ✔️ |
### DynDNS2 | dynv6.com | DynDNS2 | 60 | `token` | ✔️ | ✔️ |
| ddnss.de | DynDNS2 | 10 | update key as `token` | ⛔ | ✔️ |
- INWX.com
- deSEC.io (dedyn.io)
- DuckDNS.org
- dynv6.com
## 📦 Requirements ## 📦 Requirements
@@ -57,7 +51,7 @@ or simply clone this repo
git clone https://github.com/EV21/dynb.git git clone https://github.com/EV21/dynb.git
``` ```
If you want to add the script to you PATH, run :point_down: If you want to add the script to you PATH, run 👇
```shell ```shell
bash dynb.sh --link bash dynb.sh --link
@@ -79,7 +73,7 @@ DYNB_SERVICE_PROVIDER=inwx
## update method options: domrobot, dyndns ## update method options: domrobot, dyndns
DYNB_UPDATE_METHOD=domrobot DYNB_UPDATE_METHOD=domrobot
## ip mode could be either: 4, 6 or dual for dualstack ## ip mode could be either: 4, 6 or 64 for dualstack
DYNB_IP_MODE=64 DYNB_IP_MODE=64
## If you are using the DomRobot RPC-API enter your credentials for the web interface login here ## If you are using the DomRobot RPC-API enter your credentials for the web interface login here
@@ -92,14 +86,14 @@ DYNB_TOKEN=
## 🏃 Run ## 🏃 Run
If you have a config file just run :point_down: If you have a config file just run 👇
```bash ```bash
dynb dynb
``` ```
Alternatively you can use parameters if your system meets the relevant requirements. This example shows the long form parameter, there are also short ones.\ Alternatively you can use parameters if your system meets the relevant requirements. This example shows the long form parameter, there are also short ones.\
Call the help function :point_down: Call the help function 👇
```bash ```bash
dynb --help dynb --help
@@ -123,13 +117,13 @@ Just use the parameter `--interval 60` or the environment variable `DYNB_INTERVA
### crontab ### crontab
execute :point_down: execute 👇
```bash ```bash
crontab -e crontab -e
``` ```
then enter :point_down: to run dynb every five minutes. then add the following line 👇 to run dynb every five minutes.
```bash ```bash
*/5 * * * * $HOME/.local/bin/dynb >> $HOME/.local/share/dynb/dynb-cron.log */5 * * * * $HOME/.local/bin/dynb >> $HOME/.local/share/dynb/dynb-cron.log
@@ -155,25 +149,33 @@ services:
image: ev21/dynb image: ev21/dynb
container_name: dynb container_name: dynb
network_mode: host network_mode: host
build: stdin_open: true
context: . tty: true
dockerfile: ./Dockerfile
environment: environment:
- DYNB_DYN_DOMAIN=dyndns.example.com - DYNB_DYN_DOMAIN=dyndns.example.com
- DYNB_SERVICE_PROVIDER=inwx # Providers: deSec, duckDNS, dynv6, inwx
- DYNB_SERVICE_PROVIDER=desec
# Possible update methods are: dyndns, domrobot
- DYNB_UPDATE_METHOD=dyndns - DYNB_UPDATE_METHOD=dyndns
# IP modes: 4 (IPv4 only), 6 (IPv6 only), 64 both
- DYNB_IP_MODE=64 - DYNB_IP_MODE=64
# If your provider uses tokens use DYNB_TOKEN instead of DYNB_USERNAME and DYNB_PASSWORD
- DYNB_USERNAME=User42 - DYNB_USERNAME=User42
- DYNB_PASSWORD=SuperSecretPassword - DYNB_PASSWORD=SuperSecretPassword
- DYNB_INTERVAL=60 # The interval in seconds is the time the script waits before executing it again
- DYNB_INTERVAL=300
# TZ: Timezone setting for correct log time
- TZ=Europe/Berlin
# TERM: For colorful console output (attached mode)
- TERM=xterm-256color
``` ```
## environment variables ## environment variables
| variable | default value | description | | variable | default value | description |
| --------------------- | --------------- | -------------------------------------------------------------------------------------------------------------- | |-----------------------|-----------------|----------------------------------------------------------------------------------------------------------------|
| DYNB_DYN_DOMAIN | undefined | required; `dyndns.example.com` | | DYNB_DYN_DOMAIN | undefined | required; `dyndns.example.com` |
| DYNB_SERVICE_PROVIDER | undefined | required; `deSEC`, `duckdns`, `dynv6`, `inwx` | | DYNB_SERVICE_PROVIDER | undefined | required; `deSEC`, `duckdns`, `dynv6`, `inwx`, `ddnss` |
| DYNB_UPDATE_METHOD | undefined | required; `dyndns` or `domrobot` (with inwx) | | DYNB_UPDATE_METHOD | undefined | required; `dyndns` or `domrobot` (with inwx) |
| DYNB_IP_MODE | undefined | required; `4`, `6` or `64` for both | | 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 |

510
dynb.sh
View File

@@ -66,7 +66,7 @@ _response=
_statusHostname= _statusHostname=
_statusUsername= _statusUsername=
_statusPassword= _statusPassword=
_version=0.3.0 _version=0.3.4
_userAgent="DynB/$_version github.com/EV21/dynb" _userAgent="DynB/$_version github.com/EV21/dynb"
_configFile=$HOME/.local/share/dynb/.env _configFile=$HOME/.local/share/dynb/.env
_statusFile=/tmp/dynb.status _statusFile=/tmp/dynb.status
@@ -85,57 +85,66 @@ reset_color_modification="\e[0m"
REGEX_IPv4="^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$" REGEX_IPv4="^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$"
REGEX_IPv6="^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$" REGEX_IPv6="^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$"
function is_IPv4_address() { function is_IPv4_address
if [[ $1 =~ $REGEX_IPv4 ]] {
local ip=$1
if [[ $ip =~ $REGEX_IPv4 ]]
then return 0 then return 0
else return 1 else return 1
fi fi
} }
function is_IPv6_address() { function is_IPv6_address
if [[ $1 =~ $REGEX_IPv6 ]] {
local ip=$1
if [[ $ip =~ $REGEX_IPv6 ]]
then return 0 then return 0
else return 1 else return 1
fi fi
} }
function loopMode() { function loopMode
if [[ $_loopMode -eq 1 ]]; then {
return 0 if [[ $_loopMode -eq 1 ]]
else then return 0
return 1 else return 1
fi fi
} }
function debugMode() { function debugMode
if [[ $_debug -eq 1 ]]; then {
return 0 if [[ $_debug -eq 1 ]]
else then return 0
return 1 else return 1
fi fi
} }
function infoMessage() { function infoMessage
{
echo -e "${green_color}$(logtime) INFO: $*${reset_color_modification}" echo -e "${green_color}$(logtime) INFO: $*${reset_color_modification}"
} }
function debugMessage() { function debugMessage
if debugMode; then {
echo -e "${yellow_color}$(logtime) DEBUG: ${*}${reset_color_modification}" if debugMode
then echo -e "${yellow_color}$(logtime) DEBUG: ${*}${reset_color_modification}"
fi fi
} }
function errorMessage() { function errorMessage
{
echo -e "${red_color_bg}${bold}$(logtime) ERROR: $*${reset_color_modification}" >&2 echo -e "${red_color_bg}${bold}$(logtime) ERROR: $*${reset_color_modification}" >&2
} }
function logtime() { function logtime
{
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S") LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$LOGTIME]" echo "[$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=$( request=$(
echo "{}" | echo "{}" |
jq '(.method="nameserver.list")' | jq '(.method="nameserver.list")' |
@@ -154,7 +163,8 @@ function getMainDomain() {
_main_domain=$(echo "$_response" | jq --raw-output '.domain') _main_domain=$(echo "$_response" | jq --raw-output '.domain')
} }
function fetchDNSRecords() { function fetchDNSRecords
{
request=$( request=$(
echo "{}" | echo "{}" |
jq '(.method="'nameserver.info'")' | jq '(.method="'nameserver.info'")' |
@@ -178,47 +188,54 @@ function fetchDNSRecords() {
# requires parameter A or AAAA # requires parameter A or AAAA
# result to stdout # result to stdout
function getRecordID() { function getRecordID
echo "$_dns_records" | jq "select(.type == \"${1}\") | .id" {
echo "$_dns_records" |
jq "select(.type == \"${1}\") | .id"
} }
# requires parameter A or AAAA # requires parameter A or AAAA
# result to stdout # result to stdout
function getDNSIP() { function getDNSIP() {
echo "$_dns_records" | jq --raw-output "select(.type == \"${1}\") | .content" echo "$_dns_records" |
jq --raw-output "select(.type == \"${1}\") | .content"
} }
# requires parameter # requires parameter
# 1. param: 4 or 6 for ip version # 1. param: 4 or 6 for ip version
# 2. param: IP check server address # 2. param: IP check server address
# result to stdout # result to stdout
function getRemoteIP() { function getRemoteIP
if [[ -n $_DNS_checkServer ]]; then {
curl --silent "$_interface_str" --user-agent "$_userAgent" \ local ip_version=$1
--ipv"${1}" --dns-servers "$_DNS_checkServer" --location "${2}" local ip_check_server=$2
else curl --silent "$_interface_str" --user-agent "$_userAgent" \
curl --silent "$_interface_str" --user-agent "$_userAgent" \ --ipv"${ip_version}" --location "${ip_check_server}"
--ipv"${1}" --location "${2}" local curls_status_code=$?
fi
# shellcheck disable=2181 # shellcheck disable=2181
if [[ $? -gt 0 ]]; then if [[ $curls_status_code -gt 0 ]]; then
errorMessage "IPCheck (getRemoteIP ${1}) request failed" errorMessage "IPCheck (getRemoteIP $ip_version) request failed"
exit 1 exit 1
fi fi
} }
# requires parameter # requires parameter
# 1. param: 4 or 6 as ip version # 1. param: 4 or 6 as ip version
function updateRecord() { function updateRecord
if [[ ${1} == 4 ]]; then {
local ip_version=$1
if [[ ${ip_version} == 4 ]]
then
ID=$(getRecordID A) ID=$(getRecordID A)
IP=$_new_IPv4 IP=$_new_IPv4
fi fi
if [[ ${1} == 6 ]]; then if [[ ${ip_version} == 6 ]]
then
ID=$(getRecordID AAAA) ID=$(getRecordID AAAA)
IP=$_new_IPv6 IP=$_new_IPv6
fi fi
if [[ $IP != "" ]]; then if [[ $IP != "" ]]
then
request=$( request=$(
echo "{}" | echo "{}" |
jq '(.method="nameserver.updateRecord")' | jq '(.method="nameserver.updateRecord")' |
@@ -241,8 +258,8 @@ function updateRecord() {
fi fi
} }
# using DynDNS2 protocol function select_update_base_url
function dynupdate() { {
# default parameter values # default parameter values
myip_str=myip myip_str=myip
myipv6_str=myipv6 myipv6_str=myipv6
@@ -251,6 +268,7 @@ function dynupdate() {
DESEC_DYNDNS_UPDATE_URL="https://update.dedyn.io/?" DESEC_DYNDNS_UPDATE_URL="https://update.dedyn.io/?"
DUCKDNS_DYNDNS_UPDATE_URL="https://www.duckdns.org/update?domains=$DYNB_DYN_DOMAIN&token=$DYNB_TOKEN&" DUCKDNS_DYNDNS_UPDATE_URL="https://www.duckdns.org/update?domains=$DYNB_DYN_DOMAIN&token=$DYNB_TOKEN&"
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&"
DDNSS_DYNDNS_UPDATE_URL="https://ddnss.de/upd.php?key=$DYNB_TOKEN&host=$DYNB_DYN_DOMAIN&"
case $DYNB_SERVICE_PROVIDER in case $DYNB_SERVICE_PROVIDER in
inwx* | INWX*) inwx* | INWX*)
@@ -266,34 +284,32 @@ function dynupdate() {
;; ;;
DuckDNS* | duckdns*) DuckDNS* | duckdns*)
dyndns_update_url="${DUCKDNS_DYNDNS_UPDATE_URL}" dyndns_update_url="${DUCKDNS_DYNDNS_UPDATE_URL}"
myip_str=ipv4 myip_str=ip
myipv6_str=ipv6 myipv6_str=ipv6
;; ;;
ddnss*)
dyndns_update_url="${DDNSS_DYNDNS_UPDATE_URL}"
## we are currently not using the syntax with ip auto detection
myip_str=ip
myipv6_str=ip6
;;
*) *)
errorMessage "$DYNB_SERVICE_PROVIDER is not supported" errorMessage "$DYNB_SERVICE_PROVIDER is not supported"
exit 1 exit 1
;; ;;
esac esac
}
# pre encode ip parameters function send_request
if [[ $_is_IPv4_enabled == true ]] && [[ $_is_IPv6_enabled == true ]]; then {
dyndns_update_url="${dyndns_update_url}${myip_str}=${_new_IPv4}&${myipv6_str}=${_new_IPv6}" case $DYNB_SERVICE_PROVIDER in
fi
if [[ $_is_IPv4_enabled == true ]] && [[ $_is_IPv6_enabled == false ]]; then
dyndns_update_url="${dyndns_update_url}${myip_str}=${_new_IPv4}"
fi
if [[ $_is_IPv4_enabled == false ]] && [[ $_is_IPv6_enabled == true ]]; then
dyndns_update_url="${dyndns_update_url}${myipv6_str}=${_new_IPv6}"
fi
debugMessage "Update URL was: $dyndns_update_url"
## request ##
case $DYNB_SERVICE_PROVIDER in
inwx* | INWX*) inwx* | INWX*)
_response=$(curl --silent "$_interface_str" \ _response=$(curl --silent "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
--user "$DYNB_USERNAME":"$DYNB_PASSWORD" \ --user "$DYNB_USERNAME":"$DYNB_PASSWORD" \
"${dyndns_update_url}") "${dyndns_update_url}")
analyse_response
return $?
;; ;;
deSEC* | desec* | dedyn*) deSEC* | desec* | dedyn*)
_response=$(curl --silent "$_interface_str" \ _response=$(curl --silent "$_interface_str" \
@@ -301,41 +317,52 @@ function dynupdate() {
--header "Authorization: Token $DYNB_TOKEN" \ --header "Authorization: Token $DYNB_TOKEN" \
--get --data-urlencode "hostname=$DYNB_DYN_DOMAIN" \ --get --data-urlencode "hostname=$DYNB_DYN_DOMAIN" \
"${dyndns_update_url}") "${dyndns_update_url}")
analyse_response
return $?
;; ;;
dynv6* | duckDNS* | duckdns*) dynv6* | duckDNS* | duckdns* | ddnss*)
_response=$( _response=$(
curl --silent "$_interface_str" \ curl --silent "$_interface_str" \
--user-agent "$_userAgent" \ --user-agent "$_userAgent" \
"${dyndns_update_url}" "${dyndns_update_url}")
) analyse_response
return $?
;; ;;
esac esac
}
case $_response in function analyse_response
good* | OK* | "addresses updated") {
case $_response in
good* | OK* | "addresses updated" | *Updated*hostname*)
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
else else
infoMessage "$_response: The DynDNS update has been executed." infoMessage "The DynDNS update has been executed."
debugMessage "Response: $_response"
_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 "Nothing has changed, IP addresses are still up to date."
debugMessage "Response: $_response"
return 1 return 1
;; ;;
abuse) abuse)
errorMessage "$_response: Username is blocked due to abuse." errorMessage "Username is blocked due to abuse."
debugMessage "Response: $_response"
return 1 return 1
;; ;;
badauth | 401) *badauth* | 401)
errorMessage "$_response: Invalid username password combination." errorMessage "Invalid token or username password combination."
debugMessage "Response: $_response"
return 1 return 1
;; ;;
badagent) badagent)
errorMessage "$_response: Client disabled. Something is very wrong!" errorMessage "Client disabled. Something is very wrong!"
debugMessage "Response: $_response"
return 1 return 1
;; ;;
!donator) !donator)
@@ -350,8 +377,9 @@ function dynupdate() {
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 "Hostname supplied does not exist under specified account, enter new login credentials before performing an additional request."
debugMessage "Response: $_response"
return 1 return 1
;; ;;
numhost) numhost)
@@ -368,7 +396,7 @@ function dynupdate() {
;; ;;
*) *)
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
else else
errorMessage "unknown respnse code: $_response" errorMessage "unknown respnse code: $_response"
@@ -378,17 +406,45 @@ function dynupdate() {
esac esac
} }
function setStatus() { # using DynDNS2 protocol
function dynupdate
{
select_update_base_url
# pre encode ip parameters
if [[ $_is_IPv4_enabled == true ]] && [[ $_is_IPv6_enabled == true ]]
then
dyndns_update_url="${dyndns_update_url}${myip_str}=${_new_IPv4}&${myipv6_str}=${_new_IPv6}"
send_request
fi
if [[ $_is_IPv4_enabled == true ]] && [[ $_is_IPv6_enabled == false ]]
then
dyndns_update_url="${dyndns_update_url}${myip_str}=${_new_IPv4}"
send_request
fi
if [[ $_is_IPv4_enabled == false ]] && [[ $_is_IPv6_enabled == true ]]
then
dyndns_update_url="${dyndns_update_url}${myipv6_str}=${_new_IPv6}"
send_request
fi
request_status=$?
debugMessage "Update URL was: $dyndns_update_url"
return $request_status
}
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 and then delete $_statusFile or restart your docker container"
return 1 return 1
fi fi
;; ;;
@@ -396,8 +452,7 @@ function checkStatus() {
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
;; ;;
@@ -405,8 +460,7 @@ function checkStatus() {
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
else else rm "$_statusFile"
rm "$_statusFile"
fi fi
return 0 return 0
;; ;;
@@ -430,20 +484,20 @@ function checkStatus() {
;; ;;
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
else else 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
@@ -451,26 +505,28 @@ function checkStatus() {
# requires parameter # requires parameter
# 1. param: 4 or 6 for IP version # 1. param: 4 or 6 for IP version
function ipHasChanged() { function ipHasChanged
case ${1} in {
local ip_version=$1
case ${ip_version} in
4) 4)
remote_ip=$(getRemoteIP 4 $_ipv4_checker) remote_ip=$(getRemoteIP 4 $_ipv4_checker)
if ! is_IPv4_address "$remote_ip" if ! is_IPv4_address "$remote_ip"
then then
errorMessage "The response from the IP check server is not an IPv4 address: $remote_ip" errorMessage "The response from the IP check server is not an IPv4 address: $remote_ip"
return 0 return 1
fi fi
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then if [[ $DYNB_UPDATE_METHOD == domrobot ]]
dns_ip=$(getDNSIP A) then dns_ip=$(getDNSIP A)
else else
if [[ -n $_DNS_checkServer ]]; then if [[ -n $_DNS_checkServer ]]
dig_response=$(dig @"${_DNS_checkServer}" in a +short "$DYNB_DYN_DOMAIN") then dig_response=$(dig @"${_DNS_checkServer}" in a +short "$DYNB_DYN_DOMAIN")
else else dig_response=$(dig in a +short "$DYNB_DYN_DOMAIN")
dig_response=$(dig in a +short "$DYNB_DYN_DOMAIN")
fi fi
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 1
fi fi
# If the dns resolver lists multiple records in the answer section we filter the first line # If the dns resolver lists multiple records in the answer section we filter the first line
# using short option "-n" and not "--lines" because of alpines limited BusyBox head command # using short option "-n" and not "--lines" because of alpines limited BusyBox head command
@@ -484,161 +540,157 @@ function ipHasChanged() {
if ! is_IPv6_address "$remote_ip" if ! is_IPv6_address "$remote_ip"
then then
errorMessage "The response from the IP check server is not an IPv6 address: $remote_ip" errorMessage "The response from the IP check server is not an IPv6 address: $remote_ip"
return 0 return 1
fi fi
if [[ $DYNB_UPDATE_METHOD == domrobot ]]; then if [[ $DYNB_UPDATE_METHOD == domrobot ]]
dns_ip=$(getDNSIP AAAA) then dns_ip=$(getDNSIP AAAA)
else else
if [[ -n $_DNS_checkServer ]]; then if [[ -n $_DNS_checkServer ]]
dig_response=$(dig @"${_DNS_checkServer}" in aaaa +short "$DYNB_DYN_DOMAIN") then dig_response=$(dig @"${_DNS_checkServer}" in aaaa +short "$DYNB_DYN_DOMAIN")
else else dig_response=$(dig in aaaa +short "$DYNB_DYN_DOMAIN")
dig_response=$(dig in aaaa +short "$DYNB_DYN_DOMAIN")
fi fi
if [[ $dig_response == ";; connection timed out; no servers could be reached" ]]; then exitcode=$?
errorMessage "DNS request failed $dig_response" if [[ $exitcode -gt 0 ]]
return 0 then
errorMessage "DNS request failed with exit code: $exitcode $dig_response"
return 1
fi fi
# If the dns server lists multiple records in the answer section we filter the first line # If the dns server lists multiple records in the answer section we filter the first line
dns_ip=$(echo "$dig_response" | head -n 1) dns_ip=$(echo "$dig_response" | head -n 1)
fi fi
_new_IPv6=$remote_ip _new_IPv6=$remote_ip
debugMessage "IPv6 from remote IP check server: $_new_IPv6, IPv4 from DNS: $dns_ip" debugMessage "IPv6 from remote IP check server: $_new_IPv6, IPv6 from DNS: $dns_ip"
;; ;;
*) ;; *) ;;
esac esac
if [[ "$remote_ip" == "$dns_ip" ]]; then if [[ "$remote_ip" == "$dns_ip" ]]
return 0 then return 1
else else
case ${1} in case ${ip_version} in
4) infoMessage "New IPv4: $_new_IPv4 old was: $dns_ip";; 4) infoMessage "New IPv4: $_new_IPv4 old was: $dns_ip";;
6) infoMessage "New IPv6: $_new_IPv6 old was: $dns_ip";; 6) infoMessage "New IPv6: $_new_IPv6 old was: $dns_ip";;
esac esac
return 1 return 0
fi fi
} }
################ function handleParameters
## parameters ## {
################
function handleParameters() {
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_version == "on" ]]; then if [[ $_arg_version == "on" ]]
echo $_version then echo $_version; exit 0
exit 0
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_link == "on" ]]; then if [[ $_arg_link == "on" ]]
ln --verbose --symbolic "$(realpath "$0")" "$HOME/.local/bin/dynb" then ln --verbose --symbolic "$(realpath "$0")" "$HOME/.local/bin/dynb"; exit 0
exit 0
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_reset == "on" ]]; then if [[ $_arg_reset == "on" ]] && test -f "$_statusFile"
rm --verbose "$_statusFile" then rm --verbose "$_statusFile"; exit 0
exit 0
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_debug == "on" ]]; then if [[ $_arg_debug == "on" ]]
_debug=1 then _debug=1
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_update_method != "" ]]; then if [[ $_arg_update_method != "" ]]
DYNB_UPDATE_METHOD=$_arg_update_method then DYNB_UPDATE_METHOD=$_arg_update_method
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_ip_mode != "" ]]; then if [[ $_arg_ip_mode != "" ]]
DYNB_IP_MODE=$_arg_ip_mode then DYNB_IP_MODE=$_arg_ip_mode
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_domain != "" ]]; then if [[ $_arg_domain != "" ]]
DYNB_DYN_DOMAIN=$_arg_domain then DYNB_DYN_DOMAIN=$_arg_domain
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_service_provider != "" ]]; then if [[ $_arg_service_provider != "" ]]
DYNB_SERVICE_PROVIDER=$_arg_service_provider then DYNB_SERVICE_PROVIDER=$_arg_service_provider
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_username != "" ]]; then if [[ $_arg_username != "" ]]
DYNB_USERNAME=$_arg_username then DYNB_USERNAME=$_arg_username
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_password != "" ]]; then if [[ $_arg_password != "" ]]
DYNB_PASSWORD=$_arg_password then DYNB_PASSWORD=$_arg_password
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_token != "" ]]; then if [[ $_arg_token != "" ]]
DYNB_TOKEN=$_arg_token then DYNB_TOKEN=$_arg_token
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ $_arg_interval != "" ]]; then if [[ $_arg_interval != "" ]]
DYNB_INTERVAL=$_arg_interval then DYNB_INTERVAL=$_arg_interval
fi fi
if [[ -z $DYNB_INTERVAL ]]; then if [[ -z $DYNB_INTERVAL ]]
_loopMode=0 then _loopMode=0
elif [[ $DYNB_INTERVAL -lt _minimum_looptime ]]; then elif [[ $DYNB_INTERVAL -lt _minimum_looptime ]]
then
DYNB_INTERVAL=$_minimum_looptime DYNB_INTERVAL=$_minimum_looptime
_loopMode=1 _loopMode=1
else else _loopMode=1
_loopMode=1
fi fi
if [[ $_network_interface != "" ]]; then if [[ $_network_interface != "" ]]
_interface_str="--interface $_network_interface" then _interface_str="--interface $_network_interface"
fi fi
if [[ $DYNB_IP_MODE == d* ]]; then if [[ $DYNB_IP_MODE == d* ]]
then
_is_IPv4_enabled=true _is_IPv4_enabled=true
_is_IPv6_enabled=true _is_IPv6_enabled=true
fi fi
if [[ $DYNB_IP_MODE == *4* ]]; then if [[ $DYNB_IP_MODE == *4* ]]
_is_IPv4_enabled=true then _is_IPv4_enabled=true
fi fi
if [[ $DYNB_IP_MODE == *6* ]]; then if [[ $DYNB_IP_MODE == *6* ]]
_is_IPv6_enabled=true then _is_IPv6_enabled=true
fi fi
if [[ $DYNB_DEBUG == true ]]; then if [[ $DYNB_DEBUG == true ]]
_debug=1 then _debug=1
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ -n $DYNB_IPv4_CHECK_SITE ]]; then if [[ -n $DYNB_IPv4_CHECK_SITE ]]
_ipv4_checker=$DYNB_IPv4_CHECK_SITE then _ipv4_checker=$DYNB_IPv4_CHECK_SITE
fi fi
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ -n $DYNB_IPv6_CHECK_SITE ]]; then if [[ -n $DYNB_IPv6_CHECK_SITE ]]
_ipv6_checker=$DYNB_IPv6_CHECK_SITE then _ipv6_checker=$DYNB_IPv6_CHECK_SITE
fi fi
if [[ -n $DYNB_DNS_CHECK_SERVER ]]; then if [[ -n $DYNB_DNS_CHECK_SERVER ]]
_DNS_checkServer=$DYNB_DNS_CHECK_SERVER then _DNS_checkServer=$DYNB_DNS_CHECK_SERVER
fi fi
return 0 return 0
} }
################## function checkDependencies
## dependencies ## {
##################
function checkDependencies() {
failCounter=0 failCounter=0
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 ]]
exit 1 then exit 1
fi fi
} }
function doUnsets() { function doUnsets
{
unset _network_interface unset _network_interface
unset _DNS_checkServer unset _DNS_checkServer
unset _dns_records unset _dns_records
@@ -666,83 +718,83 @@ function doUnsets() {
unset DYNB_DEBUG unset DYNB_DEBUG
} }
function doDomrobotUpdates() { function doDomrobotUpdates
{
getMainDomain getMainDomain
fetchDNSRecords fetchDNSRecords
if [[ $_is_IPv4_enabled == true ]]; then if [[ $_is_IPv4_enabled == true ]]
ipHasChanged 4 then
if [[ $? == 1 ]]; then if ipHasChanged 4
updateRecord 4 then updateRecord 4
else else debugMessage "Skip IPv4 record update, it is already up to date"
debugMessage "Skip IPv4 record update, it is already up to date"
fi fi
fi fi
if [[ $_is_IPv6_enabled == true ]]; then if [[ $_is_IPv6_enabled == true ]]
ipHasChanged 6 then
if [[ $? == 1 ]]; then if ipHasChanged 6
updateRecord 6 then updateRecord 6
else else debugMessage "Skip IPv6 record update, it is already up to date"
debugMessage "Skip IPv6 record update, it is already up to date"
fi fi
fi fi
} }
function doDynDNS2Updates() { function doDynDNS2Updates
{
changed=0 changed=0
if [[ $_is_IPv4_enabled == true ]]; then if [[ $_is_IPv4_enabled == true ]] && ipHasChanged 4
ipHasChanged 4 then ((changed += 1))
((changed += $?))
fi fi
if [[ $_is_IPv6_enabled == true ]]; then if [[ $_is_IPv6_enabled == true ]] && ipHasChanged 6
ipHasChanged 6 then ((changed += 1))
((changed += $?))
fi fi
if [[ $changed -gt 0 ]]; then if [[ $changed -gt 0 ]]
if checkStatus; then then
if checkStatus
then
debugMessage "checkStatus has no errors, try update" debugMessage "checkStatus has no errors, try update"
if dynupdate; then if dynupdate
debugMessage "DynDNS2 update success" then 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."
fi fi
else else debugMessage "Skip DynDNS2 update, IPs are up to date or there is a connection problem"
debugMessage "Skip DynDNS2 update, IPs are up to date or there is a connection problem"
fi fi
} }
function doUpdates() { function doUpdates
if [[ $DYNB_UPDATE_METHOD == "domrobot" ]]; then {
doDomrobotUpdates if [[ $DYNB_UPDATE_METHOD == "domrobot" ]]
fi then doDomrobotUpdates
elif [[ $DYNB_UPDATE_METHOD == "dyndns" ]]
if [[ $DYNB_UPDATE_METHOD == "dyndns" ]]; then then doDynDNS2Updates
doDynDNS2Updates
fi fi
} }
function ipv6_is_not_working() { function ipv6_is_not_working
curl --ipv6 --head --silent --max-time 1 "$_internet_connectivity_test_server" > /dev/null {
curl --ipv6 --head --silent --max-time 5 $_internet_connectivity_test_server > /dev/null
status_code=$? status_code=$?
if [[ $status_code -gt 0 ]] if test $status_code -gt 0
then return 0 then return 0
else return 1 else return 1
fi fi
} }
function ipv4_is_not_working() { function ipv4_is_not_working
curl --ipv4 --head --silent --max-time 1 "$_internet_connectivity_test_server" > /dev/null {
curl --ipv4 --head --silent --max-time 5 $_internet_connectivity_test_server > /dev/null
status_code=$? status_code=$?
if [[ $status_code -gt 0 ]] if test $status_code -gt 0
then return 0 then return 0
else return 1 else return 1
fi fi
} }
function check_internet_connection() { function check_internet_connection
{
if [[ $_is_IPv4_enabled == true ]] if [[ $_is_IPv4_enabled == true ]]
then then
if ipv4_is_not_working if ipv4_is_not_working
@@ -761,25 +813,26 @@ function check_internet_connection() {
fi fi
} }
################# function main
## MAIN method ## {
#################
function dynb() {
# shellcheck disable=SC1091,SC1090 # shellcheck disable=SC1091,SC1090
source "$(dirname "$(realpath "$0")")/dynb-parsing.sh" source "$(dirname "$(realpath "$0")")/dynb-parsing.sh"
# shellcheck source=.env # shellcheck source=.env
if test -f "$_configFile"; then if test -f "$_configFile"
then
# shellcheck disable=SC1091 # shellcheck disable=SC1091
source "$_configFile" source "$_configFile"
else else
alternativeConfig="$(dirname "$(realpath "$0")")/.env" alternativeConfig="$(dirname "$(realpath "$0")")/.env"
if test -f "$alternativeConfig"; then if test -f "$alternativeConfig"
then
# shellcheck disable=SC1091 # shellcheck disable=SC1091
source "$alternativeConfig" source "$alternativeConfig"
fi fi
fi fi
if test -f "$_statusFile"; then if test -f "$_statusFile"
then
debugMessage "read previous status file" debugMessage "read previous status file"
# shellcheck disable=SC1090 # shellcheck disable=SC1090
source "$_statusFile" source "$_statusFile"
@@ -790,21 +843,20 @@ function dynb() {
checkDependencies checkDependencies
check_internet_connection check_internet_connection
if loopMode; then if loopMode
while :; do then
while :
do
doUpdates doUpdates
debugMessage "wait $DYNB_INTERVAL seconds until next check"
sleep $DYNB_INTERVAL sleep $DYNB_INTERVAL
done done
else else doUpdates
doUpdates
fi fi
doUnsets doUnsets
return 0 return 0
} }
######################
## END MAIN section ##
######################
dynb "${@}" main "${@}"
exit $? exit $?