|
|
|
|
|
by iam-TJ
814 days ago
|
|
I wrote a pure bash shell version for use on my IPv6-only networks. I initially wanted to make pure POSIX sh but the ease of being able to use ${param,,} and more importantly /dev/udp/$IP/$PORT makes bash more suitable for the use-case. #!/usr/bin/env bash
config_sys="${config_sys:-/etc/wol}"
config_user="${config_user:=$HOME/.config/wol}"
PORT="${PORT:-9999}"
cat <<EOF
WoL Wake-On-LAN Magic Packet transmitter
Copyright 2023 Tj <hacker@iam.tj>
Licensed on the terms of the GNU General Public Licence version 3.
EOF
ls() {
shopt -s nullglob
for f in $@; do
printf "%s\n" "${f##*/}"
done
}
if [ -z "$1" ]; then
cat <<-EOF
Please specify the hostname. Currently defined:
System ($config_sys/): $(ls "$config_sys/*" 2>/dev/null)
User ($config_user/): $(ls "$config_user/*" 2>/dev/null)
Config files should be named for the target host
Content is shell variable definitions
Required: IP= and MAC=
Optional: PORT= (default is ${PORT})
E.g:
MAC="60:45:cb:9f:42:fb"
IP="fddc:7e00:e001:ee80::2"
EOF
exit 1
fi
for conf in "$config_sys" "$config_user"; do
if [[ -r "$conf/$1" ]]; then
. "$conf/$1"
# don't break; allow user override
fi
done
if [[ -z "$IP" ]] || [[ -z "$MAC" ]]; then
>&2 printf "Error: required configuration missing IP='%s' MAC='%s'\n" "$IP" "$MAC"
exit 2
fi
target="/dev/udp/$IP/$PORT"
hex2char() # $1 = 2 hex digits
{
case "${#1},${1,,}" in
(2,*[!0-9a-f]*) return 2 ;;
(2,*) printf '%b' "\x$1" ;;
(*) return 1 ;;
esac
}
make_payload() # $1 = Ethernet MAC address with ":" separators
{
IFS=":" read -r -a mac < <(echo "$1")
for h in "${mac[@]}"; do
magic="$magic$(hex2char "$h")"
done
payload=""
ff="$(hex2char "ff")"
for ((i=0; i < 6; i++)); do
payload="${payload}${ff}"
done
for ((i=0; i < 16; i++)); do
payload="${payload}${magic}"
done
}
printf "Sending magic packet to %s (%s port %s [MAC %s])\n" "$1" "$IP" "$PORT" "$MAC"
make_payload "$MAC"
printf "%s" "$payload" > "$target" || printf "error: failed to send (error %s)\n" "$?"
|
|