summaryrefslogtreecommitdiffstats
path: root/core/rootfs
diff options
context:
space:
mode:
authorSimon Rettberg2020-07-08 16:12:32 +0200
committerSimon Rettberg2020-07-08 16:12:32 +0200
commitc1d6cad0e7653fcad04f27a7827a439827470092 (patch)
tree32578b2e35511271a913ac01bfb9a6b30166e0fd /core/rootfs
parent[remote-access] Tweak screen splitting (diff)
downloadmltk-c1d6cad0e7653fcad04f27a7827a439827470092.tar.gz
mltk-c1d6cad0e7653fcad04f27a7827a439827470092.tar.xz
mltk-c1d6cad0e7653fcad04f27a7827a439827470092.zip
[init/kexec/] More advanced network setup via KCL, could skip DHCP
If enough information if provided via KCL, we can skip the initial DHCP request in stage 3.1. Currently we require IP address, subnet mask and DNS server to skip DHCP. If we extend the boot server to supply a fallback/default DNS server, we could even do without DNS which would work in almost all cases. kexec-reboot has been extended to make use of this feature, but can be extended even more to provide up to date values from the current system configuration. Currently, some of the values it provides to the new kernel will be cached values from stage 3.1. kexec-reboot also honors the ipxe menu id from the KCL if given, to properly download the matching menu entry, which will take updates to the entry into account (e.g. changed URLs to kernel/init).
Diffstat (limited to 'core/rootfs')
-rw-r--r--core/rootfs/rootfs-stage31/data/inc/activate_sysconfig8
-rw-r--r--core/rootfs/rootfs-stage31/data/inc/parse_kcl37
-rw-r--r--core/rootfs/rootfs-stage31/data/inc/setup_network43
-rw-r--r--core/rootfs/rootfs-stage31/data/inc/setup_network_retry8
-rwxr-xr-xcore/rootfs/rootfs-stage31/data/inc/udhcpc-trigger29
-rwxr-xr-xcore/rootfs/rootfs-stage31/data/init1
6 files changed, 80 insertions, 46 deletions
diff --git a/core/rootfs/rootfs-stage31/data/inc/activate_sysconfig b/core/rootfs/rootfs-stage31/data/inc/activate_sysconfig
index 45f3832e..2d6015e1 100644
--- a/core/rootfs/rootfs-stage31/data/inc/activate_sysconfig
+++ b/core/rootfs/rootfs-stage31/data/inc/activate_sysconfig
@@ -42,11 +42,11 @@ merge_text_config() {
# write IP and SLX_SERVER configuration to $CONFIG
cat >> "$CONFIG" <<HEREEND
# IP Config written in stage31
-SLX_PXE_CLIENT_IP='$CLIENTIP'
+SLX_PXE_CLIENT_IP='$ip'
SLX_PXE_SERVER_IP='$SERVERIP'
-SLX_PXE_GATEWAY='$GATEWAY'
-SLX_PXE_DNS='$DNS_SERVER'
-SLX_PXE_MAC='$BRIDGEMAC'
+SLX_PXE_GATEWAY='$router'
+SLX_PXE_DNS='$dns'
+SLX_PXE_MAC='$MAC'
HEREEND
return 0
}
diff --git a/core/rootfs/rootfs-stage31/data/inc/parse_kcl b/core/rootfs/rootfs-stage31/data/inc/parse_kcl
index 95f7daf5..ba2fea8f 100644
--- a/core/rootfs/rootfs-stage31/data/inc/parse_kcl
+++ b/core/rootfs/rootfs-stage31/data/inc/parse_kcl
@@ -5,26 +5,38 @@ getip () {
}
parse_ip () {
local IPINFO=$1
- CLIENTIP="$(getip 1)"
+ export ip="$(getip 1)"
SERVERIP="$(getip 2)"
- GATEWAY="$(getip 3)"
- SUBNET_MASK="$(getip 4)"
- BROADCAST_ADDRESS="$(ipcalc -s -b "$CLIENTIP" "$SUBNET_MASK" | sed s/.*=//)"
- [ -z "$BROADCAST_ADDRESS" ] && BROADCAST_ADDRESS="255.255.255.255"
+ export router="$(getip 3)"
+ export subnet="$(getip 4)"
# we might have an idea of the dns server via preboot
- DNS_SERVER="$(getip 5)"
+ export dns="$(getip 5)"
+}
+
+parse_ipv4 () {
+ local var arg
+ var="${1%%=*}"
+ case "$var" in
+ ip|router|dns|hostname|domain|search|if|ntpsrv|subnet) ;;
+ *) return ;;
+ esac
+ arg="$( printf "%s" "${1#*=}" | tr -d "\`'\n\r" )"
+ export "$var=${arg}"
}
# read kernel command line
DEBUG=0
SPLASH=0
-read KCL < "/proc/cmdline"
+read -r KCL < "/proc/cmdline"
for opts in ${KCL}; do
case "${opts}" in
debug=*)
DEBUG=${opts#debug=}
DEBUG_SHELL=set
;;
+ ipv4.*)
+ parse_ipv4 "${opts#ipv4.}"
+ ;;
ip=*)
# process IP info
parse_ip ${opts#ip=} ;;
@@ -36,9 +48,9 @@ for opts in ${KCL}; do
BOOTIF=*)
MAC="$( echo "$opts" | cut -b 11- | tr '-' ':' | tr '[A-Z]' '[a-z]' )" ;; # make mac lowercase for udev (see setup_network)
slxsrv=*)
- SLX_KCL_SERVERS=$( echo "${opts#slxsrv=}" | tr ',' " " ) ;;
+ SLX_KCL_SERVERS="$( echo "${opts#slxsrv=}" | tr ',' " " )" ;;
slxbase=*)
- SLX_BASE_PATH=${opts#slxbase=} ;;
+ SLX_BASE_PATH="${opts#slxbase=}" ;;
splash)
SPLASH=1 ;;
nvidia)
@@ -54,8 +66,15 @@ for opts in ${KCL}; do
esac
done
+dns="${dns//,/ }"
+search="${search//,/ }"
+ntpsrv="${ntpsrv//,/ }"
+[ -z "$MAC" ] && MAC="${if//-/:}"
+
# If slxsrv was not given on command line, just use the PXE server's address
[ -z "$SLX_KCL_SERVERS" ] && [ -n "$SERVERIP" ] && SLX_KCL_SERVERS="$SERVERIP"
+# Reverse case
+[ -z "$SERVERIP" ] && SERVERIP="${SLX_KCL_SERVERS%% *}"
# Now save to config file
echo "SLX_KCL_SERVERS='$SLX_KCL_SERVERS'" >> "${FUTURE_ROOT}/opt/openslx/config"
echo "SLX_BASE_PATH='$SLX_BASE_PATH'" >> "${FUTURE_ROOT}/opt/openslx/config"
diff --git a/core/rootfs/rootfs-stage31/data/inc/setup_network b/core/rootfs/rootfs-stage31/data/inc/setup_network
index 6b97fb18..e407d173 100644
--- a/core/rootfs/rootfs-stage31/data/inc/setup_network
+++ b/core/rootfs/rootfs-stage31/data/inc/setup_network
@@ -47,28 +47,24 @@ for LINE in $IP_OUT; do
IFMAC="$( echo "${LINE#*==}" | tr 'A-Z' 'a-z' )" # udev requires mac addesses to be lowercase (a-f), see http://www.debianhelp.co.uk/udev.htm
echo "${IFACE} = ${IFMAC}"
+ if [ -z "$MAC" ]; then
+ echo "No main MAC address given, trying first interface found..."
+ MAC="$IFMAC"
+ fi
+
if [ "x$IFMAC" == "x$MAC" ]; then
+ ip link set dev "$IFACE" up
brctl addbr "$BRIDGE" || drop_shell "Could not create bridge $BRIDGE"
brctl stp "$BRIDGE" 0
brctl setfd "$BRIDGE" 0.000000000001
ip link set addr "$IFMAC" "$BRIDGE" || drop_shell "Could not set mac of $BRIDGE"
- ip link set dev "$IFACE" up
wait_for_iface "$IFACE" 8
brctl addif "$BRIDGE" "$IFACE" || drop_shell "Could not add $IFACE to $BRIDGE"
# save our variables for retry on fail
echo "IFACE=$IFACE" > /run/network.conf
- # analyze ip information from the kernel command line and put parts
- # of it into several variables
- if [ -n "$CLIENTIP" ] ; then
- # set static ip address
- ip link set dev "$BRIDGE" up
- ip addr add "$CLIENTIP/$(ipcalc -s -p "$CLIENTIP" "$SUBNET_MASK" | sed "s/.*=//")" broadcast "$BROADCAST_ADDRESS" dev "$BRIDGE"
- [ -n "$GATEWAY" ] && ip route add default via "$GATEWAY" dev "$BRIDGE"
- else
- ip link set dev "$BRIDGE" up
- fi
+ ip link set dev "$BRIDGE" up
# Ignore this device later on when systemd handles network interfaces (see hacked 99-systemd.rules in systemd data dir)
echo "SUBSYSTEM==\"net\", ACTION==\"add\", KERNEL==\"eth*\", ATTR{address}==\"$IFMAC\", TAG+=\"openslxignore\"" >> "${FUTURE_ROOT}/etc/udev/rules.d/01-ignore-boot-interface.rules"
else
@@ -90,14 +86,17 @@ done
wait_for_iface "$BRIDGE" 5
+# See if we got all required attributes via KCL, in that case skip DHCP
+# TODO: Supply DNS servers in config from boot server, so we can even work witout it
+if [ -n "$ip" ] && [ -n "$router" ] && [ -n "$dns" ]; then
+ echo "Skipping DHCP since we have new style KCL"
+ interface="${BRIDGE}" /inc/udhcpc-trigger bound && return 0
+fi
+
# udhcpc
PARAM=
-if [ -n "$CLIENTIP" ]; then
- PARAM="-r $CLIENTIP"
- echo -n "$CLIENTIP" > "/run/firstip"
-fi
-if [ -n "$GATEWAY" ]; then
- echo -n "$GATEWAY" > "/run/firstgw"
+if [ -n "$ip" ]; then
+ PARAM="-r ${ip%/*}"
fi
if [ "$USE_DHCP_UUID" = "yes" ]; then
@@ -109,15 +108,15 @@ if [ "$USE_DHCP_UUID" = "yes" ]; then
fi
# save our variables for retry on fail ff.
-echo "CLIENTIP=$CLIENTIP" >> /run/network.conf
-echo "GATEWAY=$GATEWAY" >> /run/network.conf
+echo "ip=$ip" >> /run/network.conf
+echo "router=$router" >> /run/network.conf
echo "BRIDGE=$BRIDGE" >> /run/network.conf
echo "UID=$UID" >> /run/network.conf
-udhcpc $PARAM -O hostname -O ntpsrv -O domain -O search -t 5 -T 3 -A 4 -s "/inc/udhcpc-trigger" -f -n -q -i "$BRIDGE"
+udhcpc $PARAM -O hostname -O ntpsrv -O domain -O search -O dns -t 5 -T 3 -A 4 -s "/inc/udhcpc-trigger" -f -n -q -i "$BRIDGE"
URET=$?
# if these were empty before, udhcpc might have filled them in
-[ -z "$CLIENTIP" ] && CLIENTIP=$(cat /run/firstip)
-[ -z "$GATEWAY" ] && GATEWAY=$(cat /run/firstgw)
+[ -z "$ip" ] && ip=$(cat /run/firstip)
+[ -z "$router" ] && router=$(cat /run/firstgw)
# udhcpc return value will be return value of this script
return $URET
diff --git a/core/rootfs/rootfs-stage31/data/inc/setup_network_retry b/core/rootfs/rootfs-stage31/data/inc/setup_network_retry
index c1fff39d..449c0d8f 100644
--- a/core/rootfs/rootfs-stage31/data/inc/setup_network_retry
+++ b/core/rootfs/rootfs-stage31/data/inc/setup_network_retry
@@ -17,11 +17,11 @@ for i in 1 2 3 4 5 6 7 8; do
wait_for_iface "$IFACE" "$(( 15 + i * 2 ))"
retval=$?
ip link set dev "$BRIDGE" up
- if [ "$retval" -eq 0 ] && [ "$i" -ge 4 ] && [ -n "$CLIENTIP" ] && [ -n "$GATEWAY" ]; then
+ if [ "$retval" -eq 0 ] && [ "$i" -ge 4 ] && [ -n "$ip" ] && [ -n "$router" ]; then
echo "....."
usleep 100000
echo "Checking if static IP config works...."
- if ping -c1 -w2 "$GATEWAY" &> /dev/null || ping -c1 -w2 "$SERVERIP" &> /dev/null; then
+ if ping -c1 -w2 "$router" &> /dev/null || ping -c1 -w2 "${SLX_KCL_SERVERS%% *}" &> /dev/null; then
echo "apparently so."
echo "Trying to boot without DHCP config (DNS, Hostname, ...), YMMV!"
sleep 3
@@ -33,8 +33,8 @@ for i in 1 2 3 4 5 6 7 8; do
wait_for_iface "$BRIDGE" 10
usleep 100000
- udhcpc $PARAM -O hostname -O ntpsrv -O domain -O search -t "$(( 2 + i / 2 ))" -T "$(( 4 + i ))" -s "/inc/udhcpc-trigger" -f -n -q -i "$BRIDGE" \
- || udhcpc $PARAM -O hostname -O ntpsrv -O domain -O search -t "$(( 2 + i / 2 ))" -T "$(( 4 + i ))" -s "/inc/udhcpc-trigger" -f -n -q -i "$BRIDGE"
+ udhcpc $PARAM -O hostname -O ntpsrv -O domain -O search -O dns -t "$(( 2 + i / 2 ))" -T "$(( 4 + i ))" -s "/inc/udhcpc-trigger" -f -n -q -i "$BRIDGE" \
+ || udhcpc $PARAM -O hostname -O ntpsrv -O domain -O search -O dns -t "$(( 2 + i / 2 ))" -T "$(( 4 + i ))" -s "/inc/udhcpc-trigger" -f -n -q -i "$BRIDGE"
RET="$?"
if [ "$RET" -eq 0 ]; then
diff --git a/core/rootfs/rootfs-stage31/data/inc/udhcpc-trigger b/core/rootfs/rootfs-stage31/data/inc/udhcpc-trigger
index 795dd8a0..cc7454e7 100755
--- a/core/rootfs/rootfs-stage31/data/inc/udhcpc-trigger
+++ b/core/rootfs/rootfs-stage31/data/inc/udhcpc-trigger
@@ -1,13 +1,27 @@
#!/bin/ash
-exec >> /run/stdout
exec 2>> /run/stderr
set -x
if [ "x$1" != "xbound" -a "x$1" != "xrenew" ] || [ "x$interface" != "xbr0" ] || [ -z "$ip" ]; then
+ echo "Ignoring DHCP hook '$1' for interface '$interface' -> '$ip'"
exit 0
fi
+if [ "$ip" != "${ip#*/}" ]; then # CIDR
+ cidr="$ip"
+ ip="${ip%/*}"
+elif [ -n "$mask" ]; then
+ cidr="$ip/$mask"
+else
+ if [ -z "$subnet" ]; then
+ echo "$1 event with missing subnet mask"
+ exit 1
+ fi
+ # Non-CIDR + mask
+ cidr="$ip/$( ipcalc -s -p "$ip" "$subnet" | sed 's/.*=//' )"
+fi
+
# If we already got an IP from KCL, see if it differs, and remove first if so
# We just try to prevent everything from breaking if the DHCP server doesn't
# objey the renew request by the client and hands out a new address
@@ -21,14 +35,14 @@ if [ -s "/run/firstip" ]; then
ip route del default 2>/dev/null
rm -f -- "/run/firstgw"
ip addr del "${OLD}" dev "${interface}" 2>/dev/null
- ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}"
+ ip addr add "${cidr}" dev "${interface}"
fi
else
#...no address configured yet, just add...
echo "..adding ${ip}.."
- ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}"
+ ip addr add "${cidr}" dev "${interface}"
fi
-echo -n "$ip" > "/run/firstip"
+printf "%s" "$ip" > "/run/firstip"
# Same procedure for default gateway
if [ -n "${router}" ]; then
@@ -42,7 +56,7 @@ if [ -n "${router}" ]; then
else
ip route add default via "$router"
fi
- echo -n "$router" > "/run/firstgw"
+ printf "%s" "$router" > "/run/firstgw"
fi
rm -f -- "/etc/resolv.conf"
@@ -56,7 +70,7 @@ fi
for serv in $dns; do
echo "nameserver $serv" >> "/etc/resolv.conf"
done
-if [ -z "$domain" ]; then
+if [ -z "$domain" ] && [ -n "$dns" ]; then
# try to get domain via reverse lookup if empty
echo "..trying to get domain via DNS, as DHCP didn't supply one.."
fqdn=$(timeout -t 3 nslookup "$ip" | grep -E "^Address +[0-9]+: +$ip " | head -n 1 | awk '{print $4}')
@@ -92,7 +106,7 @@ done
if [ -z "$hostname" ]; then
# as with domain, if there's no hostname, try to get via DNS
echo "..trying to get hostname via DNS, as DHCP didn't supply one.."
- [ -z "$fqdn" ] && fqdn=$(timeout -t 3 nslookup "$ip" | grep -E "^Address +[0-9]+: +$ip " | head -n 1 | awk '{print $4}')
+ [ -z "$fqdn" ] && [ -n "$dns" ] && fqdn=$(timeout -t 3 nslookup "$ip" | grep -E "^Address +[0-9]+: +$ip " | head -n 1 | awk '{print $4}')
hostname="${fqdn%%.*}"
elif [ -n "$domain" ]; then
fqdn="${hostname}.${domain}"
@@ -111,3 +125,4 @@ if [ -n "$hostname" ]; then
echo "SLX_HOSTNAME='$hostname'" >> "/run/config"
fi
+exit 0
diff --git a/core/rootfs/rootfs-stage31/data/init b/core/rootfs/rootfs-stage31/data/init
index c848493a..54102c8c 100755
--- a/core/rootfs/rootfs-stage31/data/init
+++ b/core/rootfs/rootfs-stage31/data/init
@@ -208,6 +208,7 @@ echo "Switching root...."
echo "$bench_result" > "${FUTURE_ROOT}/opt/openslx/.benchmark"
# Prepare environment (HOME is needed as a hack for nss_ldap with ssl and no caching)
unset BOOT_IMAGE initrd KCL ip slxbase slxsrv IPINFO vga ip MAC BOOTIF DEBUG OLDPWD MUTED_OUTPUT GFX
+unset ip router dns hostname domain search if ntpsrv
export HOME=/
export init="/usr/lib/systemd/systemd"
export recovery=