Initial Release
This commit is contained in:
parent
e44ed140e3
commit
101e4a039b
15 changed files with 679 additions and 0 deletions
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
src/update.d/*
|
||||||
|
!src/update.d/.do-not-delete
|
||||||
|
|
||||||
|
src/aws/*
|
||||||
|
!src/aws/.do-not-delete
|
||||||
|
|
||||||
|
src/conf.d/*
|
||||||
|
!src/conf.d/.do-not-delete
|
||||||
|
|
4
init/dynamic-ip-update.target
Normal file
4
init/dynamic-ip-update.target
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Dynamic IP Target
|
||||||
|
StopWhenUnneeded=yes
|
||||||
|
|
3
init/dynamic-ip.sysconfig
Normal file
3
init/dynamic-ip.sysconfig
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Domain Name to update:
|
||||||
|
#DOMAIN_NAME=
|
||||||
|
|
11
init/dynamic-ip.timer
Normal file
11
init/dynamic-ip.timer
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Update Dynamic IPs with DNS servers
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnBootSec=5min
|
||||||
|
OnCalendar=*:0/5
|
||||||
|
Unit=dynamic-ip-update.target
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
|
11
init/update-ipv4.service
Normal file
11
init/update-ipv4.service
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Updates IPv4 with external DNS
|
||||||
|
Wants=dynamic-ip.timer
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=/etc/sysconfig/dynamic-ip-update
|
||||||
|
ExecStart=/etc/dynamic-ip/update-ipv4 ${DOMAIN_NAME}
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=dynamic-ip-update.target
|
||||||
|
|
11
init/update-ipv6.service
Normal file
11
init/update-ipv6.service
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Updates IPv6 with external DNS
|
||||||
|
Wants=dynamic-ip.timer
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=/etc/sysconfig/dynamic-ip-update
|
||||||
|
ExecStart=/etc/dynamic-ip/update-ipv6 ${DOMAIN_NAME}
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=dynamic-ip-update.target
|
||||||
|
|
66
src/agents.d/aws-sg
Executable file
66
src/agents.d/aws-sg
Executable file
|
@ -0,0 +1,66 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Internal Initialization
|
||||||
|
|
||||||
|
source "${DIP_FUNCTIONS}"
|
||||||
|
|
||||||
|
if [[ -r "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_NAME}.conf" ]]; then
|
||||||
|
source "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_NAME}.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -r "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_EXEC}.conf" ]]; then
|
||||||
|
source "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_EXEC}.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$agent_aws_sg_id" ]]; then
|
||||||
|
logerr "ERROR: Need 'agent_aws_sg_id' to be defined to your Security Group ID"
|
||||||
|
exit 99
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d "${DIP_BASE_DIR}/aws" ]]; then
|
||||||
|
if [[ ! -r "${DIP_BASE_DIR}/aws/config" ]]; then
|
||||||
|
logerr "ERROR: AWS config file not found: '${DIP_BASE_DIR}/aws/config'"
|
||||||
|
exit 99
|
||||||
|
elif [[ ! -r "${DIP_BASE_DIR}/aws/credentials" ]]; then
|
||||||
|
logerr "ERROR: AWS credentials file not found: '${DIP_BASE_DIR}/aws/credentials'"
|
||||||
|
exit 99
|
||||||
|
else
|
||||||
|
export AWS_CONFIG_FILE="${DIP_BASE_DIR}/aws/config"
|
||||||
|
export AWS_SHARED_CREDENTIALS_FILE="${DIP_BASE_DIR}/aws/credentials"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
logerr "ERROR: AWS config directory not found. '${DIP_BASE_DIR}/aws/' is expected to exist and contain 'config' and 'credentials' for AWS access."
|
||||||
|
exit 99
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$DIP_CUR_IP" ]] || [[ -z "$DIP_OLD_IP" ]]; then
|
||||||
|
logerr "ERROR: Agent expects currentip, and existingip."
|
||||||
|
exit 98
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Main
|
||||||
|
|
||||||
|
if valid_ipv4 "$DIP_CUR_IP"; then
|
||||||
|
if [[ "${DIP_CUR_IP}/32" = "${DIP_OLD_IP}/32" ]]; then
|
||||||
|
log "No changes required."
|
||||||
|
else
|
||||||
|
log "Updating Security Group IP"
|
||||||
|
aws ec2 revoke-security-group-ingress --group-id "${agent_aws_sg_id}" --ip-permissions "[{\"IpProtocol\": \"-1\", \"IpRanges\": [{\"CidrIp\": \"${DIP_OLD_IP}/32\"}]}]"
|
||||||
|
aws ec2 authorize-security-group-ingress --group-id "${agent_aws_sg_id}" --ip-permissions "[{\"IpProtocol\": \"-1\", \"IpRanges\": [{\"CidrIp\": \"${DIP_CUR_IP}/32\"}]}]"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if valid_ipv6 "$DIP_CUR_IP"; then
|
||||||
|
currentprefix=$(getIPv6Prefix $DIP_CUR_IP)
|
||||||
|
existingprefix=$(getIPv6Prefix $DIP_OLD_IP)
|
||||||
|
|
||||||
|
if [[ "$currentprefix" = "$existingprefix" ]]; then
|
||||||
|
log "No changes required."
|
||||||
|
else
|
||||||
|
log "Updating Security Group IPv6"
|
||||||
|
aws ec2 revoke-security-group-ingress --group-id "${agent_aws-sg_id}" --ip-permissions "[{\"IpProtocol\": \"-1\", \"Ipv6Ranges\": [{\"CidrIpv6\": \"${existingprefix}\"}]}]"
|
||||||
|
aws ec2 authorize-security-group-ingress --group-id "${agent_aws-sg_id}" --ip-permissions "[{\"IpProtocol\": \"-1\", \"Ipv6Ranges\": [{\"CidrIpv6\": \"${currentprefix}\"}]}]"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
52
src/agents.d/update-dns-r53
Executable file
52
src/agents.d/update-dns-r53
Executable file
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Internal Initialization
|
||||||
|
|
||||||
|
source "${DIP_FUNCTIONS}"
|
||||||
|
|
||||||
|
if [[ -r "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_NAME}.conf" ]]; then
|
||||||
|
source "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_NAME}.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -r "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_EXEC}.conf" ]]; then
|
||||||
|
source "${DIP_BASE_DIR}/conf.d/${DIP_AGENT_EXEC}.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$agent_update_dns_r53_id" ]]; then
|
||||||
|
logerr "ERROR: Need 'agent_update_dns_r53_id' to be defined to your Route53 Domain ID"
|
||||||
|
exit 99
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d "${DIP_BASE_DIR}/aws" ]]; then
|
||||||
|
if [[ ! -r "${DIP_BASE_DIR}/aws/config" ]]; then
|
||||||
|
logerr "ERROR: AWS config file not found: '${DIP_BASE_DIR}/aws/config'"
|
||||||
|
exit 99
|
||||||
|
elif [[ ! -r "${DIP_BASE_DIR}/aws/credentials" ]]; then
|
||||||
|
logerr "ERROR: AWS credentials file not found: '${DIP_BASE_DIR}/aws/credentials'"
|
||||||
|
exit 99
|
||||||
|
else
|
||||||
|
export AWS_CONFIG_FILE="${DIP_BASE_DIR}/aws/config"
|
||||||
|
export AWS_SHARED_CREDENTIALS_FILE="${DIP_BASE_DIR}/aws/credentials"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
logerr "ERROR: AWS config directory not found. '${DIP_BASE_DIR}/aws/' is expected to exist and contain 'config' and 'credentials' for AWS access."
|
||||||
|
exit 99
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$DIP_CUR_IP" ]] || [[ -z "$DIP_OLD_IP" ]] || [[ -z "$DIP_RECORD" ]]; then
|
||||||
|
logerr "ERROR: Agent expects currentip, existingip, and record."
|
||||||
|
exit 98
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Main
|
||||||
|
|
||||||
|
if valid_ipv4 "$DIP_CUR_IP"; then
|
||||||
|
log "Updating Route53 DNS IPv4 Record"
|
||||||
|
/usr/local/bin/cli53 rc --replace "$agent_update_dns_r53_id" "${DIP_RECORD}. 300 A ${DIP_CUR_IP}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if valid_ipv6 "$DIP_CUR_IP"; then
|
||||||
|
log "Updating Route53 DNS IPv6 Record"
|
||||||
|
/usr/local/bin/cli53 rc --replace "$agent_update_dns_r53_id" "${DIP_RECORD}. 300 AAAA ${DIP_CUR_IP}"
|
||||||
|
fi
|
0
src/aws/.do-not-delete
Normal file
0
src/aws/.do-not-delete
Normal file
8
src/checks.lst
Normal file
8
src/checks.lst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Example using a router's automatic wan-ip name as Ubiquity routers do:
|
||||||
|
#dig +short @172.17.0.1 wan-ip.mydomain
|
||||||
|
|
||||||
|
# Use OpenDNS to get MyIP
|
||||||
|
dig +short myip.opendns.com @resolver1.opendns.com
|
||||||
|
|
||||||
|
# Use ipecho.com to get MyIP
|
||||||
|
curl --silent ipecho.net/plain
|
0
src/conf.d/.do-not-delete
Normal file
0
src/conf.d/.do-not-delete
Normal file
502
src/dynamic-ip
Executable file
502
src/dynamic-ip
Executable file
|
@ -0,0 +1,502 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
trim() {
|
||||||
|
local extglobWasOff=1
|
||||||
|
local var=$1
|
||||||
|
|
||||||
|
shopt extglob >/dev/null && extglobWasOff=0
|
||||||
|
(( extglobWasOff )) && shopt -s extglob
|
||||||
|
var=${var##+([[:space:]])}
|
||||||
|
var=${var%%+([[:space:]])}
|
||||||
|
(( extglobWasOff )) && shopt -u extglob
|
||||||
|
echo -n "$var"
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_ip() {
|
||||||
|
local ip=$1
|
||||||
|
|
||||||
|
if [[ "${prog_name,,}" == "update-ipv4" ]]; then
|
||||||
|
valid_ipv4 "$ip"
|
||||||
|
return $?
|
||||||
|
elif [[ "${prog_name,,}" == "update-ipv6" ]]; then
|
||||||
|
valid_ipv6 "$ip"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
return 89
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_ipv4() {
|
||||||
|
local ip=$1
|
||||||
|
local stat=1
|
||||||
|
|
||||||
|
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||||
|
OIFS=$IFS
|
||||||
|
IFS='.'
|
||||||
|
ip=($ip)
|
||||||
|
IFS=$OIFS
|
||||||
|
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
|
||||||
|
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
|
||||||
|
stat=$?
|
||||||
|
fi
|
||||||
|
return $stat
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_ipv6() {
|
||||||
|
local ip=$1
|
||||||
|
|
||||||
|
if [[ $ip =~ ^$|^[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}$ ]]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecords() {
|
||||||
|
local file=$1
|
||||||
|
local r
|
||||||
|
|
||||||
|
if [[ ! -r "$file" ]]; then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
while read r;
|
||||||
|
do
|
||||||
|
r=$(trim "$r")
|
||||||
|
[[ ${r:0:1} == '#' ]] && continue
|
||||||
|
[[ -z "$r" ]] && continue
|
||||||
|
|
||||||
|
echo "$r"
|
||||||
|
done <"$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getIPv4() {
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
local -a checks
|
||||||
|
|
||||||
|
if [[ ! -f "${script_dir}/checks.lst" ]]
|
||||||
|
then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
mapfile -t checks < "${script_dir}/checks.lst"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in "${checks[@]}"
|
||||||
|
do
|
||||||
|
i=$(trim "$i")
|
||||||
|
[[ ${i:0:1} == '#' ]] && continue
|
||||||
|
[[ -z "$i" ]] && continue
|
||||||
|
|
||||||
|
result=$($i)
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]]
|
||||||
|
then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if valid_ipv4 "$result"
|
||||||
|
then
|
||||||
|
echo "$result"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
getIPv6() {
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
|
||||||
|
result=$(/sbin/ip -6 addr | grep inet6 | awk -F '[ \t]+|/' '{print $3}' | grep -v ^::1 | grep -v ^fe80)
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]]; then
|
||||||
|
return 1
|
||||||
|
elif valid_ipv6 "$result"; then
|
||||||
|
echo "$result"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getDnsNS() {
|
||||||
|
local rec=$1
|
||||||
|
local domain=$(sed 's/[^.]*\.\([^.]*\..*\)/\1/' <<<"$rec")
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
|
||||||
|
result=$(dig +short @8.8.8.8 NS $domain | sed -e 's/.$//')
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -eq 0 ]]
|
||||||
|
then
|
||||||
|
for d in $result
|
||||||
|
do
|
||||||
|
echo "$d"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
logerr "ERROR"
|
||||||
|
return $err
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getDnsIP() {
|
||||||
|
local rec=$1
|
||||||
|
local rectype
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
|
||||||
|
for i in $(getDnsNS "$rec")
|
||||||
|
do
|
||||||
|
[[ "$i" = "ERROR" ]] && return 1
|
||||||
|
|
||||||
|
if [[ "${prog_name,,}" == "update-ipv4" ]]; then
|
||||||
|
rectype=A
|
||||||
|
elif [[ "${prog_name,,}" == "update-ipv6" ]]; then
|
||||||
|
rectype=AAAA
|
||||||
|
else
|
||||||
|
return 88
|
||||||
|
fi
|
||||||
|
|
||||||
|
result=$(dig +short @${i} ${rectype} ${rec} | head -n1)
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]] || [[ -z "$result" ]]; then
|
||||||
|
logerr "ERROR: DNS lookup for $i"
|
||||||
|
continue
|
||||||
|
elif valid_ip "$result"; then
|
||||||
|
echo "$result"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
logerr "ERROR: Lookup failed with: $result"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
getIPv6Prefix() {
|
||||||
|
local rec=$1
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
|
||||||
|
if valid_ipv6 $rec
|
||||||
|
then
|
||||||
|
result=$(echo "$rec" | cut -d':' -f1-4)
|
||||||
|
result="${result}::/64"
|
||||||
|
echo "$result"
|
||||||
|
else
|
||||||
|
logerr "Not IPv6"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getZabbixProxyIP() {
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
|
||||||
|
result=$(awk -F "=" '/^Server/ { print $2 }' /etc/zabbix/zabbix_proxy.conf)
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]]
|
||||||
|
then
|
||||||
|
return 1
|
||||||
|
elif valid_ip "$result"
|
||||||
|
then
|
||||||
|
echo "$result"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getShorewallIP() {
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
|
||||||
|
result=$(awk -F "=" '/HOME_IP/ { print $2 }' /etc/shorewall/params)
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]]
|
||||||
|
then
|
||||||
|
return 1
|
||||||
|
elif valid_ip "$result"
|
||||||
|
then
|
||||||
|
echo "$result"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getCachedIP() {
|
||||||
|
local result
|
||||||
|
local err
|
||||||
|
|
||||||
|
result=$(<"$HOME/.cached_ip")
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]]; then
|
||||||
|
return 1
|
||||||
|
elif valid_ip "$result"; then
|
||||||
|
echo "$result"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
logerr() {
|
||||||
|
>&2 log $*
|
||||||
|
}
|
||||||
|
|
||||||
|
run-parts() {
|
||||||
|
# Ignore *~ and *, scripts
|
||||||
|
for i in $(LC_ALL=C; echo ${1%/}/*[^~,]) ; do
|
||||||
|
[[ -d $i ]] && continue
|
||||||
|
# Don't run *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} scripts
|
||||||
|
[[ "${i%.cfsaved}" != "${i}" ]] && continue
|
||||||
|
[[ "${i%.rpmsave}" != "${i}" ]] && continue
|
||||||
|
[[ "${i%.rpmorig}" != "${i}" ]] && continue
|
||||||
|
[[ "${i%.rpmnew}" != "${i}" ]] && continue
|
||||||
|
[[ "${i%.swp}" != "${i}" ]] && continue
|
||||||
|
[[ "${i%,v}" != "${i}" ]] && continue
|
||||||
|
|
||||||
|
# jobs.deny prevents specific files from being executed
|
||||||
|
# jobs.allow prohibits all non-named jobs from being run.
|
||||||
|
# can be used in conjunction but there's no reason to do so.
|
||||||
|
if [[ -r "${1}/jobs.deny" ]]; then
|
||||||
|
grep -q "^$(basename "$i")$" "${1}/jobs.deny" && continue
|
||||||
|
fi
|
||||||
|
if [[ -r "${1}/jobs.allow" ]]; then
|
||||||
|
grep -q "^$(basename "$i")$" "${1}/jobs.allow" || continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e $i ]]; then
|
||||||
|
if [[ -r "${1}/whitelist" ]]; then
|
||||||
|
grep -q "^$(basename "$i")$" "${1}/whitelist" && continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -x "$i" ]]; then
|
||||||
|
# run executable files
|
||||||
|
echo "$i"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
run-hook() {
|
||||||
|
local hook_dir=$1
|
||||||
|
local errors=0
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [[ ! -d "${hook_dir}" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
while read s
|
||||||
|
do
|
||||||
|
log "Running agent: $(basename "$s")"
|
||||||
|
DIP_FUNCTIONS="$(readlink -f "$0")" \
|
||||||
|
DIP_AGENT_NAME="$(basename "$(readlink -f "$s")")" \
|
||||||
|
DIP_AGENT_EXEC="$(basename "$s")" \
|
||||||
|
DIP_AGENT_DIR="$(dirname "$(readlink -f "$s")")" \
|
||||||
|
DIP_BASE_DIR="${script_dir}" \
|
||||||
|
DIP_CUR_IP="$1" \
|
||||||
|
DIP_OLD_IP="$2" \
|
||||||
|
DIP_RECORD="$3" \
|
||||||
|
"$s" $*
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]]; then
|
||||||
|
let errors++
|
||||||
|
fi
|
||||||
|
done < <(run-parts "${hook_dir}")
|
||||||
|
|
||||||
|
return $errors
|
||||||
|
}
|
||||||
|
|
||||||
|
run-update() {
|
||||||
|
local cip=$1
|
||||||
|
local eip=$2
|
||||||
|
local rec=$3
|
||||||
|
|
||||||
|
if [[ "$cip" != "$eip" ]]
|
||||||
|
then
|
||||||
|
run-hook "${script_dir}/update.d" "$cip" "$eip" "$rec"
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -gt 0 ]]; then
|
||||||
|
return $err
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "No change detected"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Caches current local IP so it doesn't have to every time.
|
||||||
|
getCurrentLocalIP() {
|
||||||
|
local cip
|
||||||
|
|
||||||
|
if [[ -z "$currentip" ]]; then
|
||||||
|
case "${prog_name,,}" in
|
||||||
|
update-ipv4) cip=$(getIPv4) || return 1;;
|
||||||
|
update-ipv6) cip=$(getIPv6) || return 1;;
|
||||||
|
*) return 3;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "$cip"
|
||||||
|
else
|
||||||
|
case "${prog_name,,}" in
|
||||||
|
update-ipv4) valid_ipv4 "$currentip" || return 1;;
|
||||||
|
update-ipv6) valid_ipv6 "$currentip" || return 1;;
|
||||||
|
*) return 3;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "$currentip"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentIP() {
|
||||||
|
local i=$1
|
||||||
|
|
||||||
|
if [[ -z "$i" ]]; then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
case "${prog_name,,}" in
|
||||||
|
update-ipv4)
|
||||||
|
log "Checking if internet IP has changed for $i"
|
||||||
|
currentip=$(getCurrentLocalIP) || return $?
|
||||||
|
externalip=$(getDnsIP $i) || return 2
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
update-ipv6)
|
||||||
|
log "Checking if internet IPv6 has changed for $i"
|
||||||
|
currentip=$(getCurrentLocalIP) || return $?
|
||||||
|
externalip=$(getDnsIP $i) || return 2
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
*) logerr "FATAL"; return 3 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check-update() {
|
||||||
|
local arg=$1
|
||||||
|
local d
|
||||||
|
|
||||||
|
if [[ -n "$arg" ]]; then
|
||||||
|
getCurrentIP $arg
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
case $err in
|
||||||
|
0) if [[ "$currentip" != "$externalip" ]]; then
|
||||||
|
log "Updates found: $externalip is not $currentip"
|
||||||
|
log "Running Agents for $arg"
|
||||||
|
run-update "$currentip" "$externalip" "$arg"
|
||||||
|
err=$?
|
||||||
|
|
||||||
|
if [[ $err -ne 0 ]]; then
|
||||||
|
logerr "WARNING: Agents had $err errors"
|
||||||
|
else
|
||||||
|
log "Agents ran successfully"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "No change detected"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
1) logerr "ERROR: Failed to determine current public IP"
|
||||||
|
logerr "DEBUG: dig output '$currentip'"
|
||||||
|
exit 4
|
||||||
|
;;
|
||||||
|
2) logerr "ERROR: Failed to determine external DNS IP"
|
||||||
|
logerr "DEBUG: dig output '$externalip'"
|
||||||
|
;;
|
||||||
|
*) logerr "Unknown fatal error occurred"
|
||||||
|
eclogerrho "(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }"
|
||||||
|
exit $err
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
if [[ -n "$record" ]]; then
|
||||||
|
check-update "$record"
|
||||||
|
elif [[ -n "$record_file" ]]; then
|
||||||
|
for d in $(getRecords "$record_file"); do
|
||||||
|
check-update "$d"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
return 99
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# This section doesn't run if this script was sourced.
|
||||||
|
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
# Internal Initialization
|
||||||
|
|
||||||
|
prog_name=$(basename "$0")
|
||||||
|
script_dir=$(dirname "$(readlink -f "$0")")
|
||||||
|
|
||||||
|
if [[ -z "$1" ]]; then
|
||||||
|
logerr "ERROR: Need to provide a DNS record or file to look-up"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
if [[ -r "$1" ]]; then
|
||||||
|
record_file=$1
|
||||||
|
else
|
||||||
|
record=$1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
## Locking
|
||||||
|
|
||||||
|
if [[ "$USER" = "root" ]]; then
|
||||||
|
LOCKFILE="/var/lock/$(basename "$0")"
|
||||||
|
else
|
||||||
|
LOCKFILE="/tmp/${USER}/lock/$(basename "$0")"
|
||||||
|
mkdir -p "/tmp/${USER}/lock"
|
||||||
|
fi
|
||||||
|
LOCKFD=99
|
||||||
|
|
||||||
|
# PRIVATE
|
||||||
|
_lock() { flock -$1 $LOCKFD; }
|
||||||
|
_no_more_locking() { _lock u; _lock xn && rm -f $LOCKFILE; }
|
||||||
|
_prepare_locking() { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }
|
||||||
|
|
||||||
|
# ON START
|
||||||
|
_prepare_locking
|
||||||
|
|
||||||
|
# PUBLIC
|
||||||
|
exlock_now() { _lock xn; } # obtain an exclusive lock immediately or fail
|
||||||
|
exlock() { _lock x; } # obtain an exclusive lock
|
||||||
|
shlock() { _lock s; } # obtain a shared lock
|
||||||
|
unlock() { _lock u; } # drop a lock
|
||||||
|
|
||||||
|
### BEGIN OF SCRIPT ###
|
||||||
|
|
||||||
|
# Simplest example is avoiding running multiple instances of script.
|
||||||
|
exlock_now || exit 1
|
||||||
|
|
||||||
|
# Remember! Lock file is removed when one of the scripts exits and it is
|
||||||
|
# the only script holding the lock or lock is not acquired at all.
|
||||||
|
|
||||||
|
|
||||||
|
# Main
|
||||||
|
|
||||||
|
case "${prog_name,,}" in
|
||||||
|
update-ipv4) check-update; exit $? ;;
|
||||||
|
update-ipv6) check-update; exit $? ;;
|
||||||
|
*) logerr "ERROR: Unknown update method"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
fi
|
1
src/update-ipv4
Symbolic link
1
src/update-ipv4
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
dynamic-ip
|
1
src/update-ipv6
Symbolic link
1
src/update-ipv6
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
dynamic-ip
|
0
src/update.d/.do-not-delete
Normal file
0
src/update.d/.do-not-delete
Normal file
Loading…
Reference in a new issue