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