From: Georgios Kontaxis Date: Mon, 22 Jun 2026 15:43:09 +0000 (+0000) Subject: etherwake: wait for the interface to come up before transmitting X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=c444c5a472459f5a352fbc0015e21f2362f57fc8;p=openwrt-packages.git etherwake: wait for the interface to come up before transmitting Signed-off-by: Georgios Kontaxis --- diff --git a/net/etherwake/files/etherwake.config b/net/etherwake/files/etherwake.config index cf025dcad..4847aa1d1 100644 --- a/net/etherwake/files/etherwake.config +++ b/net/etherwake/files/etherwake.config @@ -1,17 +1,27 @@ config 'etherwake' 'setup' # interface to use, defaults to 'eth0' #option 'interface' 'eth0' + + # maximum wait during system boot for the interface to be up + # - defaults to 10 seconds + # - 0 seconds means no wait or check that the interface is up + #option 'interface_timeout' '10' + # send wake-up packet to the broadcast address, defaults to off #option 'broadcast' 'off' config 'target' # name for the target #option 'name' 'example' + # mac address of the machine to wake up #option 'mac' '00:11:22:33:44:55' + # (optional) 6-byte secureOn password in ethernet hex format #option 'secureon' 'aa:bb:cc:dd:ee:ff' + # (optional) 4-byte secureOn password in dotted decimal format #option 'secureon' '170.187.204.221' + # wake up on system start, defaults to off #option 'wakeonboot' 'off' diff --git a/net/etherwake/files/etherwake.init b/net/etherwake/files/etherwake.init index 43396e5eb..b3b091f1b 100644 --- a/net/etherwake/files/etherwake.init +++ b/net/etherwake/files/etherwake.init @@ -2,104 +2,174 @@ # Copyright (C) 2009 OpenWrt.org NAME='etherwake' -START=60 +START=99 PROGRAM='/usr/bin/etherwake' -start() -{ - local value='' +boot() { + etherwake_boot & +} + +etherwake_boot() { + etherwake_load_config_setup + + local iface="${ETHERWAKE_CONFIG_SETUP_IFACE}" + local timeout="${ETHERWAKE_CONFIG_SETUP_TIMEOUT}" + + if [ "${timeout}" != "0" ] && + ! etherwake_wait_for_iface "${iface}" "${timeout}"; then + logger -t "${NAME}" \ + "Interface '${iface}' did not come up within ${timeout} seconds" + return 1 + fi + + start +} + +ETHERWAKE_CONFIG_LOADED='0' +ETHERWAKE_CONFIG_SETUP_IFACE='' +ETHERWAKE_CONFIG_SETUP_TIMEOUT=1 +ETHERWAKE_CONFIG_SETUP_BROADCAST='0' + +etherwake_load_config_setup() { + [ "${ETHERWAKE_CONFIG_LOADED}" != "0" ] && return config_load "${NAME}" - # interface - config_get value 'setup' 'interface' 'eth0' - append PROGRAM "-i ${value}" + config_get ETHERWAKE_CONFIG_SETUP_IFACE 'setup' 'interface' 'eth0' - # broadcast - config_get_bool value 'setup' 'broadcast' '0' - [ "${value}" -ne 0 ] && append PROGRAM '-b' + config_get ETHERWAKE_CONFIG_SETUP_TIMEOUT 'setup' 'interface_timeout' + case "${ETHERWAKE_CONFIG_SETUP_TIMEOUT}" in + ''|*[!0-9]*) + ETHERWAKE_CONFIG_SETUP_TIMEOUT=10 + ;; + esac - # wake up targets - config_foreach etherwake_start target $* + config_get_bool ETHERWAKE_CONFIG_SETUP_BROADCAST 'setup' 'broadcast' '0' + + ETHERWAKE_CONFIG_LOADED=1 } -etherwake_start() -{ - local section="$1" - shift +# etherwake_wait_for_iface [] +# +# wait up to 'timeout' seconds for interface 'iface' to come up. +# - when 'timeout' is set to 0 the function returns immediately +# without checking the status of the interface +# - default 'timeout' is 1 +etherwake_wait_for_iface() { + local iface="$1" + local timeout="${2:-1}" + + [ -n "${iface}" ] || return 1 + + local interval=1 + local elapsed=0 + + while [ "${elapsed}" -lt "${timeout}" ]; do + if [ "$(ubus call network.interface."${iface}" status 2> /dev/null | + jsonfilter -e '@.up' 2> /dev/null)" = "true" ]; then + logger -t "${NAME}" \ + "Interface '${iface}' is up after ${elapsed} seconds" + return 0 + fi + + sleep "${interval}" + elapsed=$((elapsed + interval)) + done + + return 1 +} + +ETHERWAKE_LAST_ERROR=0 + +start() { + etherwake_load_config_setup + + ETHERWAKE_LAST_ERROR=0 - local names="$*" + config_foreach etherwake_start target \ + "${ETHERWAKE_CONFIG_SETUP_IFACE}" \ + "${ETHERWAKE_CONFIG_SETUP_BROADCAST}" "$@" + + return ${ETHERWAKE_LAST_ERROR} +} + +# etherwake_start
[] +etherwake_start() { + local section="$1"; shift + local iface="$1"; shift + local broadcast="$1"; shift + local names="$@" local value='' - local target='' + local filter='' - if [ -z "${names}" ] - then - # check if boot target + # are we focusing on all targets that should wake up when this script runs + # or specific names? + if [ -z "${names}" ]; then config_get_bool value "${section}" 'wakeonboot' '0' [ "${value}" -eq 0 ] && return 0 - # wake up target - do_etherwake "${section}" - return $? - else - # name - config_get value "${section}" 'name' - [ -z "${value}" ] && return 0 - - for target in ${names} - do - [ "${value}" != "${target}" ] && continue - - # wake up target - do_etherwake "${section}" - return $? - done + do_etherwake "${section}" "${iface}" "${broadcast}" || ETHERWAKE_LAST_ERROR=$? + return 0 fi + + config_get value "${section}" 'name' + [ -z "${value}" ] && return 0 + + for filter in ${names}; do + [ "${value}" != "${filter}" ] && continue + + do_etherwake "${section}" "${iface}" "${broadcast}" || ETHERWAKE_LAST_ERROR=$? + break + done + + return 0 } # execute etherwake command for target -do_etherwake() -{ +do_etherwake() { local section="$1" - local value='' - local password='' - local args='' + local iface="$2" + local broadcast="$3" + local section_name='' + local mac='' + local password='' + local secureon='' + + config_get section_name "${section}" 'name' "${section}" + + config_get mac "${section}" 'mac' + [ -z "${mac}" ] && { + logger -t "${NAME}" "Target '${section_name}' has no 'mac' address" + return 1 + } # password (legacy option) - config_get value "${section}" 'password' - [ -n "${value}" ] && { - password=$(etherwake_password "${value}") - append args "-p ${password}" + config_get password "${section}" 'password' + [ -n "${password}" ] && { + password=$(etherwake_password "${password}") } - # secureOn password - config_get value "${section}" 'secureon' - [ -n "${value}" ] && append args "-p ${value}" + config_get secureon "${section}" 'secureon' - # name - config_get section_name "${section}" 'name' - [ -z "${section_name}" ] && section_name="${section}" + set -- + [ -n "${iface}" ] && set -- "$@" -i "${iface}" + [ "${broadcast}" = "1" ] && set -- "$@" -b + [ -n "${password}" ] && set -- "$@" -p "${password}" + [ -n "${secureon}" ] && set -- "$@" -p "${secureon}" + set -- "$@" "${mac}" - # mac address - config_get value "${section}" 'mac' - [ -z "${value}" ] && { - echo "Target '${section_name}' has no 'mac' address"; return 1; } - append args "${value}" + logger -t "${NAME}" "Waking up '${section_name}' via ${PROGRAM} $*" + + "${PROGRAM}" "$@" - # execute command - echo "Waking up '${section_name}' via ${PROGRAM}${args:+ ${args}}" - ${PROGRAM} ${args} return $? } - -# prepare hex password (support legacy option) -etherwake_password() -{ +# make string look like ethernet hex format (support legacy password option) +etherwake_password() { local delimiter=':' - local password=`echo "$1" | sed "s/../&${delimiter}/g"` + local password=$(echo "$1" | sed "s/../&${delimiter}/g") echo "${password%${delimiter}}" - return }