diff --git a/tailscale/rootfs/etc/NetworkManager/dispatcher.d/protect-subnets b/tailscale/rootfs/etc/NetworkManager/dispatcher.d/protect-subnets index 3c14671d2..1e7e707b5 100755 --- a/tailscale/rootfs/etc/NetworkManager/dispatcher.d/protect-subnets +++ b/tailscale/rootfs/etc/NetworkManager/dispatcher.d/protect-subnets @@ -3,36 +3,19 @@ export LOG_FD # The shebang 'with-contenv-merge' above is identical with 'with-contenv', but doesn't clear the current environment containing the dispatcher variables -# Redirect outputs to the log (&2 is already set up as pipe by s6) -exec 1>&2 -if [[ "${LOG_FD:-}" =~ ^[0-9]+$ ]]; then - eval "exec ${LOG_FD}>&1" || true -fi +readonly NM_DISPATCHER_LISTENER_QUEUE=/run/nm-dispatcher-listener-queue -function halt-app() { - bashio::log.error "Failed to protect subnet routes. Halting app to prevent network loss." - echo -n 1 > /run/s6-linux-init-container-results/exitcode - exec /run/s6/basedir/bin/halt -} +# Redirect outputs to the log (though &2 is already set up as pipe by s6) +exec &> /proc/1/fd/1 +bashio::log.reinitialize_output case "${NM_DISPATCHER_ACTION}" in - up|down) - bashio::log.info "Handling Network Manager action ${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}" - unprotect-subnet-routes - if ! protect-subnet-routes; then - # Better stop app than risking losing all network connections - halt-app - fi - ;; - dhcp4-change|dhcp6-change) - # Do anything only when the addresses are really changed - if [[ "$(unprotect-subnet-routes test)" != "$(protect-subnet-routes test)" ]]; then - bashio::log.info "Handling Network Manager action ${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}" - unprotect-subnet-routes - if ! protect-subnet-routes tested; then - # Better stop app than risking losing all network connections - halt-app - fi + up|down|dhcp4-change|dhcp6-change) + bashio::log.debug "Received Network Manager action ${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}" + if ! echo "${DEVICE_IP_IFACE-} ${NM_DISPATCHER_ACTION}" > "${NM_DISPATCHER_LISTENER_QUEUE}"; then + bashio::log.fatal "Failed to send nm-dispatcher action to listener. Halting app to prevent network loss." + echo -n 1 > /run/s6-linux-init-container-results/exitcode + exec /run/s6/basedir/bin/halt fi ;; connectivity-change) diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/dependencies.d/local-network b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/dependencies.d/local-network similarity index 100% rename from tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/dependencies.d/local-network rename to tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/dependencies.d/local-network diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/down b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/down new file mode 100644 index 000000000..5a86836db --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/down @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-protect-subnets/finish diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/finish b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/finish new file mode 100755 index 000000000..c36ff3296 --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/finish @@ -0,0 +1,9 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +export LOG_FD +# ============================================================================== +# Home Assistant Community App: Tailscale +# Remove subnet protection +# ============================================================================== + +unprotect-subnet-routes diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/run b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/run new file mode 100755 index 000000000..713a27b62 --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/run @@ -0,0 +1,9 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +export LOG_FD +# ============================================================================== +# Home Assistant Community App: Tailscale +# Prevent local subnets to be routed toward the tailnet +# ============================================================================== + +protect-subnet-routes diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/type b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/type new file mode 100644 index 000000000..bdd22a185 --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/type @@ -0,0 +1 @@ +oneshot diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/up b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/up new file mode 100644 index 000000000..854fa8af2 --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-protect-subnets/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-protect-subnets/run diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/dependencies.d/init-protect-subnets b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/dependencies.d/init-protect-subnets new file mode 100644 index 000000000..e69de29bb diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/finish b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/finish new file mode 100755 index 000000000..5d57033cc --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/finish @@ -0,0 +1,32 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +export LOG_FD +# ============================================================================== +# Home Assistant Community App: Tailscale +# Take down the S6 supervision tree when nm-dispatcher-listener fails +# ============================================================================== +readonly exit_code_container=$(&- +rm -rf "${NM_DISPATCHER_LISTENER_QUEUE}" + +bashio::log.info \ + "Service ${service} exited with code ${exit_code_service}" \ + "(by signal ${exit_code_signal})" + +if [[ "${exit_code_service}" -eq 256 ]]; then + if [[ "${exit_code_signal}" -ne 15 && "${exit_code_container}" -eq 0 ]]; then + echo $((128 + $exit_code_signal)) > /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/notification-fd b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/notification-fd new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/notification-fd @@ -0,0 +1 @@ +3 diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/run b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/run new file mode 100755 index 000000000..4d7d26154 --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/run @@ -0,0 +1,52 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +export LOG_FD +# ============================================================================== +# Home Assistant Community App: Tailscale +# Runs the nm-dispatcher-listener service +# ============================================================================== + +readonly NM_DISPATCHER_LISTENER_QUEUE=/run/nm-dispatcher-listener-queue + +declare action +declare subnet_routes_to_unprotect +declare subnet_routes_to_protect + +mkfifo "${NM_DISPATCHER_LISTENER_QUEUE}" + +# Pin it to prevent closing it by other processes +exec 4<>"${NM_DISPATCHER_LISTENER_QUEUE}" + +# We need to delay the starting of the dependent services until listener queue is created +echo "" >&3 +exec 3>&- + +while IFS= read -r -u 4 action +do + case "${action}" in + *up|*down) + bashio::log.info "Handling Network Manager action ${action}" + unprotect-subnet-routes + bashio::try protect-subnet-routes + if bashio::try.failed; then + bashio::exit.nok "Failed to protect subnet routes. Halting app to prevent network loss." + fi + ;; + *dhcp4-change|*dhcp6-change) + # Do anything only when the addresses are really changed + subnet_routes_to_unprotect="$(unprotect-subnet-routes test)" + subnet_routes_to_protect="$(protect-subnet-routes test)" + if ! bashio::var.equals "${subnet_routes_to_unprotect}" "${subnet_routes_to_protect}"; then + bashio::log.info "Handling Network Manager action ${action}" + unprotect-subnet-routes + bashio::try protect-subnet-routes tested + if bashio::try.failed; then + bashio::exit.nok "Failed to protect subnet routes. Halting app to prevent network loss." + fi + fi + ;; + *) + bashio::exit.nok "Unknown Network Manager action ${action}" + ;; + esac +done diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/type b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/type new file mode 100644 index 000000000..5883cff0c --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher-listener/type @@ -0,0 +1 @@ +longrun diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/dependencies.d/nm-dispatcher-listener b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/dependencies.d/nm-dispatcher-listener new file mode 100644 index 000000000..e69de29bb diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/finish b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/finish similarity index 84% rename from tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/finish rename to tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/finish index cbc296213..c72c83493 100755 --- a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/finish +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/finish @@ -3,21 +3,19 @@ export LOG_FD # ============================================================================== # Home Assistant Community App: Tailscale -# Take down the S6 supervision tree when protect-subnets fails +# Take down the S6 supervision tree when nm-dispatcher fails # ============================================================================== readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode fi [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/run b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/run similarity index 84% rename from tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/run rename to tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/run index aa872cf26..1a1366f02 100755 --- a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/run +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/run @@ -3,11 +3,9 @@ export LOG_FD # ============================================================================== # Home Assistant Community App: Tailscale -# Prevent local subnets to be routed toward the tailnet +# Runs the nm-dispatcher service # ============================================================================== -protect-subnet-routes - # runs scripts in /etc/NetworkManager/dispatcher.d # --debug is used to prevent logging to syslog (HA cli) exec /usr/libexec/nm-dispatcher --persist --debug > /dev/null diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/type b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/type new file mode 100644 index 000000000..5883cff0c --- /dev/null +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/nm-dispatcher/type @@ -0,0 +1 @@ +longrun diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/contents.d/init-protect-subnets b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/contents.d/init-protect-subnets new file mode 100644 index 000000000..e69de29bb diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/contents.d/nm-dispatcher b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/contents.d/nm-dispatcher new file mode 100644 index 000000000..e69de29bb diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/contents.d/nm-dispatcher-listener b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/contents.d/nm-dispatcher-listener new file mode 100644 index 000000000..e69de29bb diff --git a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/type b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/type index 5883cff0c..757b42211 100644 --- a/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/type +++ b/tailscale/rootfs/etc/s6-overlay/s6-rc.d/protect-subnets/type @@ -1 +1 @@ -longrun +bundle