utils: ixll: Add link-local wrappers for ping/ssh/scp

This commit is contained in:
Tobias Waldekranz
2024-04-19 15:25:02 +02:00
committed by Joachim Wiberg
parent 0c917ab37e
commit 36716dab42
2 changed files with 238 additions and 0 deletions
Executable
+92
View File
@@ -0,0 +1,92 @@
#!/bin/sh
set -e
. $(dirname $(readlink -f "$0"))/libll.sh
usage()
{
local me="$(basename $0)"
cat <<EOF
usage: $me [-A] <command> [<args>]
Wrap various existing network facilities such that an interface name
may be supplied in places where a hostname is otherwise expected.
Options:
-A
For commands requiring authentication, use password
authentication with username "admin" and password "admin".
Commands:
peer <iface>
Return the address of the first IPv6 neighbor to respond on
<iface>'s local LAN.
ping <iface>
Send ping to all-hosts group, with link-local scope, on <iface>,
suppressing loopbacked packets.
ssh <iface> [<ssh-arguments>]
ssh(1) to the neighboring host on <iface>.
scp <src> <dst>
scp(1) from <src> to <dst>, but any host specified in either
<src> or <dst> is assumed to be an interface name, which is
expanded to a neighboring host on that interface.
${0} help
Display this message.
Examples:
Start interactive ssh(1) session to the neighbor to eth0
$me ssh eth0
Copy /etc/hostname from the neighbor to eth0, using admin/admin
$me -A scp eth0:/etc/hostname /tmp/hostname
EOF
}
while getopts "A" opt; do
case ${opt} in
A)
LLSSH_USER=admin
LLSSH_PASS=admin
;;
esac
done
shift $((OPTIND - 1))
if [ $# -lt 1 ]; then
usage && exit 1
fi
cmd="$1"
shift
case "$cmd" in
help)
usage && exit 0
;;
peer)
llpeer "$@"
;;
ping)
llping "$@"
;;
scp)
llscp "$@"
;;
ssh)
llssh "$@"
;;
*)
echo "Unknown command \"$cmd\"" >2
exit 1
;;
esac
+146
View File
@@ -0,0 +1,146 @@
# Utility functions for communicating with IPv6 neighbors on the local
# LAN
# Usage: llping <iface>
#
# Send ping to all-hosts group, with link-local scope, on <iface>,
# suppressing loopbacked packets.
llping()
{
local iface="$1"
shift
ping -L ff02::1%$iface "$@"
}
# Usage: llpeer <iface>
#
# Return the address of the first IPv6 neighbor to respond on
# <iface>'s local LAN. It is thus typically only useful in scenarios
# where only one neighbor exists
llpeer()
{
local iface="$1"
shift
llping $iface -c1 "$@" | \
awk '/bytes from/ { sub(/:$/, "", $4); print($4); exit(0); }'
}
llssh_expand()
{
local old_ifs="$IFS"
local orig="$1"
local fmt="$2"
local peer=
local user=
local iface=
IFS=@
set $1
IFS="$old_ifs"
case $# in
1)
user="$LLSSH_USER"
iface="$1"
;;
2)
user="$1"
iface="$2"
;;
*)
echo "Error: Invalid peer \"$orig1\"" >&2
return 1
;;
esac
if [ -d "/sys/class/net/$iface" ]; then
peer="$(llpeer $iface -w3)"
else
peer="$iface"
fi
if [ ! "$peer" ]; then
echo "Error: No peer responded on $iface" >&2
return 1
fi
case "$fmt" in
ssh)
;;
scp)
peer="[$peer]"
;;
*)
echo "Internal error: Invalid format \"$fmt\"" >&2
return 1
;;
esac
[ "$user" ] && peer="$user@$peer"
echo $peer
}
# Usage: llssh <destination> [<ssh-args>]
#
# ssh(1) to <destination>, but if the host matches an existing
# interface name, expand it to a neighboring host on that interface.
llssh()
{
local remote="$1"
shift
local peer="$(llssh_expand $remote ssh)"
[ "$peer" ] || return 1
local sshpasscmd=
[ "$LLSSH_PASS" ] && sshpasscmd="sshpass -p$LLSSH_PASS $LLSSHPASS_OPTS"
$sshpasscmd ssh $LLSSH_OPTS $peer "$@"
}
llscp_expand()
{
local orig="$1"
local old_ifs="$IFS"
local peer=
IFS=:
set $@
IFS="$old_ifs"
case $# in
1)
echo "$1"
;;
2)
peer="$(llssh_expand $1 scp)"
[ "$peer" ] || return 1
echo "$peer:$2"
;;
*)
echo "Error: Invalid location \"$orig1\"" >&2
return 1
;;
esac
}
# Usage: llscp <src> <dst>
#
# scp(1) from <src> to <dst>, but expand any host specified in either
# <src> or <dst>, which matches an existing interface name, to a
# neighboring host on that interface.
llscp()
{
local src="$(llscp_expand $1)"
local dst="$(llscp_expand $2)"
[ "$src" -a "$dst" ] || return 1
shift 2
local sshpasscmd=
[ "$LLSSH_PASS" ] && sshpasscmd="sshpass -p$LLSSH_PASS $LLSSHPASS_OPTS"
$sshpasscmd scp $LLSCP_OPTS "$src" "$dst"
}