Last active
February 10, 2022 18:53
-
-
Save JadedDragoon/d7f01852ba7b8570a4adc7d7e95b69c1 to your computer and use it in GitHub Desktop.
Robust scripts for managing DHCP6-PD templating for configurations which must have the actual IPv6 address. Requires jq, tsp, and dhcpcd.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# we need seperate logging because dhcpcd-run-hooks eats stdout and stderr | |
# rather doing something sane like passing it back to dhcpcd (and then systemd) | |
. /usr/local/lib/logging.bash | |
################################################################################ | |
# Configuration begins here. | |
################################################################################ | |
. /usr/local/etc/dhcp-template.conf | |
################################################################################ | |
# Script begins here. | |
################################################################################ | |
. /usr/local/lib/dhcp-template.bash | |
if [[ "${1}" == '-exec' ]]; then | |
bashlog 'info' "Executing task for ${reason}." | |
get_vals | |
write_configs | |
if [[ ${log_verbosity} -ge 8 ]]; then | |
bashlog 'debug' "Environment:\n $(printenv | sort)" | |
fi | |
else | |
bashlog 'debug' "Hook reason is ${reason}." | |
case "${reason}" in | |
DELEGATED6 | BOUND | BOUND6 | REBIND | REBIND6) | |
for util in "${required_commands[@]}"; do | |
if ! command -v "${util}" >/dev/null 2>&1; then printf '%s' "Utility \'${util}\' unavailable. Aborting."; exit 1; fi | |
done | |
# Because we do not control execution and cannot afford to block | |
# execution at any point, flocks are not a viable approach. Here we use | |
# task-spooler to queue execution of the important parts of this script | |
# instead. | |
bashlog 'info' "Queueing task for ${reason}." | |
bashlog 'debug' "Running: tsp -f \"${script_name[0]}\" -exec" | |
tsp -f "${script_name[0]}" -exec | |
;; | |
esac | |
fi | |
# vim: ts=4:sw=4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# dhcpd6.template | |
default-lease-time 2592000; | |
preferred-lifetime 604800; | |
option dhcp-renewal-time 3600; | |
option dhcp-rebinding-time 7200; | |
allow leasequery; | |
option dhcp6.preference 255; | |
# Server side command to enable rapid-commit (2 packet exchange) | |
#option dhcp6.rapid-commit; | |
option dhcp6.info-refresh-time 21600; | |
authoritative; | |
log-facility local7; | |
subnet6 $[PREFIX]::/$[PFSUBNET] { | |
pool6 { | |
option dhcp6.name-servers 2606:4700:4700::1111, 2606:4700:4700::1001; | |
max-lease-time 300; | |
range6 $[PREFIX]::2:1 $[PREFIX]::2:FFFF; | |
allow unknown-clients; | |
} | |
pool6 { | |
option dhcp6.name-servers fe80::FFFF:18ff:fea5:6c28, 2606:4700:4700::1111, 2606:4700:4700::1001; | |
option dhcp6.domain-search "subdomain.example.net", "example.net"; | |
deny unknown-clients; | |
range6 $[PREFIX]::1:101 $[PREFIX]::1:FFFF; | |
host destynovamk4 { | |
host-identifier option client-id 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD; | |
fixed-address6 $[PREFIX]::1:1; | |
} | |
host drido { | |
host-identifier option client-id 11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:FF; | |
fixed-address6 $[PREFIX]::1:2; | |
} | |
host zappan { | |
host-identifier option client-id 22:33:44:55:66:77:88:99:AA:BB:CC:DD:FF:00; | |
fixed-address6 $[PREFIX]::1:3; | |
} | |
} | |
} | |
# vim: ts=4:sw=4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################################ | |
# Configuration begins here. | |
################################################################################ | |
wan_interface='wan' | |
lan_interface='lan' | |
log_identifier='dhcpcd-exit-hook' | |
declare -A templates=( | |
['/etc/dhcpd6.template.conf']="/etc/dhcpd6-${lan_interface}.conf" | |
) | |
services=( | |
dhcpd6@${lan_interface} | |
) | |
json_conf='/var/lib/dhcpcd/exit-hook-conf.json' | |
#log_verbosity=7 #enable debugging | |
# vim: ts=4:sw=4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare -r script_name=$(readlink -f ${BASH_SOURCE[0]}) | |
declare -r conf_ver='0.4.0' | |
declare -r required_commands=(tsp jq) | |
IFS=' ' | |
read -r -d '' header <<'EOF' | |
#####################################\ | |
# #\ | |
# DO NOT EDIT THIS FILE #\ | |
# #\ | |
# This file is periodicly replaced. #\ | |
# Edit the template instead. #\ | |
##################################### | |
EOF | |
upsert_transform() { | |
if [[ ! -f "${json_conf}~" ]]; then printf '%s' '{}' > "${json_conf}~"; fi | |
if ! jq \ | |
--arg match "${1}" \ | |
--arg value "${2}" \ | |
--arg ver "${conf_ver}" \ | |
--arg lu "$(date -Ins)" \ | |
'.transforms[$match] = $value | .version = $ver | .lastupdate = $lu' \ | |
"${json_conf}" \ | |
1>"${json_conf}~" 2>&1 | |
then | |
printf '%s' 'Failed assigning values to temporary JSON.' | |
return 1 | |
fi | |
mv "${json_conf}~" "${json_conf}" 2>&1 || printf '%s' 'Failed overwriting existing JSON' && return 2 | |
} | |
delegated_prefix() { | |
bashlog 'info' "Delegated IPv6 LAN Prefix. Updating services configuration..." | |
prefixes=(${new_delegated_dhcp6_prefix//[^a-fA-F0-9:\/ ]/}) | |
prefix=$(printf '%s' "${prefixes[0]}" | sed -E 's/::[a-fA-F0-9]{1,4}\/[0-9]{1,3}$//g') | |
subnet=$(printf '%s' "${prefixes[0]}" | sed -E 's/^[a-fA-F0-9:]+\///g') | |
bashlog 'debug' " Prefix resolution: ${prefixes[*]} -> ${prefix} ${subnet}" | |
bashlog 'info' " Found Prefix: ${prefix}::/${subnet}" | |
bashlog 'info' ' Updating json.' | |
bashlog 'err' "$(upsert_transform 'lan6prefix' ${prefix})" | |
bashlog 'err' "$(upsert_transform 'lan6subnet' ${subnet})" | |
bashlog 'info' ' Done.' | |
} | |
bound_addr() { | |
bashlog 'info' "Bound new IP to WAN interface. Updating services configuration..." | |
case "${reason}" in | |
BOUND | REBIND) | |
address=$(printf '%s' "${new_ip_address}" | grep -P '((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])') | |
;; | |
BOUND6 | REBIND6) | |
address=$(printf '%s' "${new_dhcp6_ia_na1_ia_addr1}" | grep -P '^(([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]))$') | |
;; | |
esac | |
if [[ -z ${address} ]]; then bashlog 'err' ' Failed to determine new ip address.'; exit 1; fi | |
bashlog 'info' " Found IP Address: ${address}" | |
bashlog 'info' ' Updating json.' | |
case "${reason}" in | |
BOUND | REBIND) | |
bashlog 'err' "$(upsert_transform 'wan4addr' ${address})" | |
;; | |
BOUND6 | REBIND6) | |
bashlog 'err' "$(upsert_transform 'wan6addr' ${address})" | |
;; | |
esac | |
bashlog 'info' ' Done.' | |
} | |
inplace_dance() { | |
read -r -d '' data | |
printf '%s' "${data}" 1> "${1}~" | |
mv "${1}~" "${1}" | |
} | |
get_vals() { | |
case "${reason}" in | |
DELEGATED6) | |
bashlog 'debug' "${interface} must match ${lan_interface}" | |
if [[ "${interface}" == "${lan_interface}" ]]; then delegated_prefix; fi | |
;; | |
BOUND | BOUND6 | REBIND | REBIND6) | |
bashlog 'debug' "${interface} must match ${wan_interface}" | |
if [[ "${interface}" == "${wan_interface}" ]]; then bound_addr; fi | |
;; | |
esac | |
} | |
write_configs() { | |
declare -A transforms="$(\ | |
jq --join-output '.transforms | [ to_entries[] | "["+(.key|@sh)+"]="+(.value|@sh) ] | "("+join(" ")+")"' ${json_conf} \ | |
)" | |
bashlog 'info' 'Generating config files from templates...' | |
bashlog 'debug' " Templates: ${!templates[@]}" | |
for template in "${!templates[@]}"; do | |
bashlog 'debug' " Processing - ${template} into ${templates[${template}]}" | |
bashlog 'debug' ' Striping comments and empty lines.' | |
bashlog 'err' $(\ | |
sed -E 's/#.*$//g' "${template}" |\ | |
sed -E '/^\s*$/d' |\ | |
inplace_dance "${templates[$template]}" \ | |
2>&1) | |
for match in "${!transforms[@]}"; do | |
bashlog 'debug' " Transforming \$[${match^^}] into ${transforms[$match]}." | |
bashlog 'err' $(\ | |
sed "s/\$\[${match^^}\]/${transforms[$match]}/g" "${templates[${template}]}" |\ | |
inplace_dance "${templates[$template]}" \ | |
2>&1) | |
done | |
bashlog 'debug' ' Adding header.' | |
bashlog 'err' $(\ | |
sed "1 i # TEMPLATE FILE: ${template}" "${templates[${template}]}" |\ | |
sed "1 i ${header}" |\ | |
inplace_dance "${templates[$template]}" \ | |
2>&1) | |
bashlog 'err' $(chmod 644 "${templates[${template}]}" 2>&1) | |
done | |
bashlog 'info' " Done." | |
bashlog 'info' "(Re)Starting services..." | |
for service in "${services[@]}"; do | |
bashlog 'debug' "Restarting ${service}." | |
bashlog 'err' "$(systemctl restart ${service} 2>&1)" | |
done | |
bashlog 'info' " Done." | |
} | |
# vim: ts=4:sw=4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
log_verbosity=6 #info | |
stdout_verbosity=4 #warning | |
stderr_verbosity=3 #error | |
log_identifier='bash-logging' | |
log_console='off' | |
bashlog() { | |
if [ -n "$2" ]; then | |
string="${@:2}" | |
errlvl=8 | |
case "$1" in | |
emerg | emergency | panic) | |
errlvl=0 | |
;; | |
alert) | |
errlvl=1 | |
string="!!!ALERT!!! $string" | |
;; | |
crit | critical) | |
errlvl=2 | |
string="CRITICAL: $string" | |
;; | |
err | error) | |
errlvl=3 | |
string="ERROR: $string" | |
;; | |
warn | warning) | |
errlvl=4 | |
string="Warning: $string" | |
;; | |
note | notice | notify) | |
errlvl=5 | |
string="notice: $string" | |
;; | |
info | inform | information) | |
errlvl=6 | |
;; | |
debug) | |
errlvl=7 | |
string="debug: $string" | |
;; | |
esac | |
# quick and dirty test to see if logging is working | |
if [[ $log_verbosity -ge 8 ]]; then echo "testing ${@:2}" | logger -p 7 -t ${log_identifier}; fi | |
# log to syslog/journald | |
if [[ $log_verbosity -ge $errlvl ]]; then | |
printf "${string}" | logger -p $errlvl -t "${log_identifier}" | |
fi | |
# log to console as well | |
if [[ ${log_console} == 'on' ]]; then | |
if [[ $stdout_verbosity -ge $errlvl && $stderr_verbosity -lt $errlvl ]]; then | |
printf '%s' "${string}" | |
fi | |
if [[ $stderr_verbosity -ge $errlvl ]]; then | |
printf '%s' "${string}" >&2 | |
fi | |
fi | |
fi | |
} | |
# vim: ts=4:sw=4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# script to force update dhcp6 templates on command | |
. /usr/local/lib/logging.bash | |
. /usr/local/etc/dhcp-template.conf | |
. /usr/local/lib/dhcp-template.bash | |
IFS=' ' | |
log_console='on' | |
log_verbosity=7 | |
write_configs | |
# vim: ts=4:sw=4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment