460d2c99f9
git snapshot
141 lines
4.4 KiB
Diff
141 lines
4.4 KiB
Diff
From ceca74ccc397795db68ca6ffbe49d65af2178a50 Mon Sep 17 00:00:00 2001
|
|
From: Martin Wilck <mwilck@suse.de>
|
|
Date: Sat, 11 Jul 2020 00:15:34 +0200
|
|
Subject: [PATCH] dracut-functions: add ip_params_for_remote_addr() helper
|
|
|
|
This helper function takes a remote IP address, and tries to
|
|
determine the dracut command line arguments ip= and ifname= that
|
|
will make this remote address reachable during boot.
|
|
|
|
Functionality was taken from the module-setup.sh scripts of 95iscsi and 95nfs,
|
|
cleaned up and fixed some issues in particular with statically configured
|
|
networks, where the old code would print the unsupported string
|
|
"$ifname:static".
|
|
---
|
|
dracut-functions.sh | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 114 insertions(+)
|
|
|
|
diff --git a/dracut-functions.sh b/dracut-functions.sh
|
|
index b5c28248..07ae88c0 100755
|
|
--- a/dracut-functions.sh
|
|
+++ b/dracut-functions.sh
|
|
@@ -728,3 +728,117 @@ btrfs_devs() {
|
|
printf -- "%s\n" "$_dev"
|
|
done
|
|
}
|
|
+
|
|
+iface_for_remote_addr() {
|
|
+ set -- $(ip -o route get to "$1")
|
|
+ echo $3
|
|
+}
|
|
+
|
|
+local_addr_for_remote_addr() {
|
|
+ set -- $(ip -o route get to "$1")
|
|
+ echo $5
|
|
+}
|
|
+
|
|
+peer_for_addr() {
|
|
+ local addr=$1
|
|
+ local qtd
|
|
+
|
|
+ # quote periods in IPv4 address
|
|
+ qtd=${addr//./\\.}
|
|
+ ip -o addr show | \
|
|
+ sed -n 's%^.* '"$qtd"' peer \([0-9a-f.:]\{1,\}\(/[0-9]*\)\?\).*$%\1%p'
|
|
+}
|
|
+
|
|
+netmask_for_addr() {
|
|
+ local addr=$1
|
|
+ local qtd
|
|
+
|
|
+ # quote periods in IPv4 address
|
|
+ qtd=${addr//./\\.}
|
|
+ ip -o addr show | sed -n 's,^.* '"$qtd"'/\([0-9]*\) .*$,\1,p'
|
|
+}
|
|
+
|
|
+gateway_for_iface() {
|
|
+ local ifname=$1 addr=$2
|
|
+
|
|
+ case $addr in
|
|
+ *.*) proto=4;;
|
|
+ *:*) proto=6;;
|
|
+ *) return;;
|
|
+ esac
|
|
+ ip -o -$proto route show | \
|
|
+ sed -n "s/^default via \([0-9a-z.:]\{1,\}\) dev $ifname .*\$/\1/p"
|
|
+}
|
|
+
|
|
+# This works only for ifcfg-style network configuration!
|
|
+bootproto_for_iface() {
|
|
+ local ifname=$1
|
|
+ local dir
|
|
+
|
|
+ # follow ifcfg settings for boot protocol
|
|
+ for dir in network-scripts network; do
|
|
+ [ -f "/etc/sysconfig/$dir/ifcfg-$ifname" ] && {
|
|
+ sed -n "s/BOOTPROTO=[\"']\?\([[:alnum:]]\{1,\}\)[\"']\?.*\$/\1/p" \
|
|
+ "/etc/sysconfig/$dir/ifcfg-$ifname"
|
|
+ return
|
|
+ }
|
|
+ done
|
|
+}
|
|
+
|
|
+is_unbracketed_ipv6_address() {
|
|
+ strglob "$1" '*:*' && ! strglob "$1" '\[*:*\]'
|
|
+}
|
|
+
|
|
+# Create an ip= string to set up networking such that the given
|
|
+# remote address can be reached
|
|
+ip_params_for_remote_addr() {
|
|
+ local remote_addr=$1
|
|
+ local ifname local_addr peer netmask= gateway ifmac
|
|
+
|
|
+ [[ $remote_addr ]] || return 1
|
|
+ ifname=$(iface_for_remote_addr "$remote_addr")
|
|
+ [[ $ifname ]] || {
|
|
+ berror "failed to determine interface to connect to $remote_addr"
|
|
+ return 1
|
|
+ }
|
|
+
|
|
+ # ifname clause to bind the interface name to a MAC address
|
|
+ if [ -d "/sys/class/net/$ifname/bonding" ]; then
|
|
+ dinfo "Found bonded interface '${ifname}'. Make sure to provide an appropriate 'bond=' cmdline."
|
|
+ elif [ -e "/sys/class/net/$ifname/address" ] ; then
|
|
+ ifmac=$(cat "/sys/class/net/$ifname/address")
|
|
+ [[ $ifmac ]] && printf 'ifname=%s:%s ' "${ifname}" "${ifmac}"
|
|
+ fi
|
|
+
|
|
+ bootproto=$(bootproto_for_iface "$ifname")
|
|
+ case $bootproto in
|
|
+ dhcp|dhcp6|auto6) ;;
|
|
+ dhcp4)
|
|
+ bootproto=dhcp;;
|
|
+ static*|"")
|
|
+ bootproto=;;
|
|
+ *)
|
|
+ derror "bootproto \"$bootproto\" is unsupported by dracut, trying static configuration"
|
|
+ bootproto=;;
|
|
+ esac
|
|
+ if [[ $bootproto ]]; then
|
|
+ printf 'ip=%s:%s ' "${ifname}" "${bootproto}"
|
|
+ else
|
|
+ local_addr=$(local_addr_for_remote_addr "$remote_addr")
|
|
+ [[ $local_addr ]] || {
|
|
+ berror "failed to determine local address to connect to $remote_addr"
|
|
+ return 1
|
|
+ }
|
|
+ peer=$(peer_for_addr "$local_addr")
|
|
+ # Set peer or netmask, but not both
|
|
+ [[ $peer ]] || netmask=$(netmask_for_addr "$local_addr")
|
|
+ gateway=$(gateway_for_iface "$ifname" "$local_addr")
|
|
+ # Quote IPv6 addresses with brackets
|
|
+ is_unbracketed_ipv6_address "$local_addr" && local_addr="[$local_addr]"
|
|
+ is_unbracketed_ipv6_address "$peer" && peer="[$peer]"
|
|
+ is_unbracketed_ipv6_address "$gateway" && gateway="[$gateway]"
|
|
+ printf 'ip=%s:%s:%s:%s::%s:none ' \
|
|
+ "${local_addr}" "${peer}" "${gateway}" "${netmask}" "${ifname}"
|
|
+ fi
|
|
+
|
|
+}
|
|
|