summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Bauer2020-07-28 14:57:16 +0200
committerJonathan Bauer2020-07-29 12:55:52 +0200
commit092ec5bd8ea2f1913543e85287e143fe5b139103 (patch)
tree641a5b42ea72edc39a057c0202f4d4405c732604
parent[slx-splash] reactivate systemd messages if fbsplash fails (diff)
downloadsystemd-init-092ec5bd8ea2f1913543e85287e143fe5b139103.tar.gz
systemd-init-092ec5bd8ea2f1913543e85287e143fe5b139103.tar.xz
systemd-init-092ec5bd8ea2f1913543e85287e143fe5b139103.zip
[slx-network] new style KCL
-rw-r--r--modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh146
-rwxr-xr-xmodules.d/slx-network/scripts/setup-bootif-network.stage326
-rwxr-xr-xmodules.d/slx-network/scripts/udhcpc-trigger.stage334
3 files changed, 125 insertions, 81 deletions
diff --git a/modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh b/modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh
index 56abb680..3dfd7edd 100644
--- a/modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh
+++ b/modules.d/slx-network/hooks/parse-ipxe-network-kcl.sh
@@ -1,89 +1,106 @@
#!/bin/bash
#
-# TODO VLAN support
+# Script parsing the kernel command line to get the IP configuration from
+# (i)PXE. Supports either the older
+# ip=<CLIENT_IP>:<PXE_SERVER_IP>:<GATEWAY>:<NETMASK> format or our new format
+# consisting of 'ipv4.<attr>' key/value pairs. Valid attributes are: ip, router,
+# dns, hostname, domain, search, if, ntpsrv, subnet.
command -v getarg >/dev/null || . /lib/dracut-lib.sh
# static names for the boot interface and its bridge
-declare -rg BOOTIF_NAME="boot0"
-declare -rg BRIDGE_NAME="br0"
-declare -rg RUNTIME_CONF="/run/openslx/network.conf"
-mkdir -p "${RUNTIME_CONF%/*}"
-# Get all the ip-related arguments from the KCL
-parse_kernel_command_line() {
- ## KCL "BOOTIF": MAC address of the interface that DHCP'ed during PXE
- declare -g BOOTIF="$(getarg BOOTIF=)"
- # Remove the hardware type prefix of BOOTIF if it has 20 chars to get
- # the plain MAC address. The hardware type prefix has length 3, e.g. "01-".
- if [ -n "${BOOTIF}" ] && [ ${#BOOTIF} -eq 20 ]; then
- BOOTIF="${BOOTIF#???}"
- BOOTIF="${BOOTIF//-/:}"
+declare -rg bootif_name="boot0"
+declare -rg bridge_name="br0"
+
+# parse old syslinux style 'ip=...' and 'BOOTIF=...' parameters
+parse_kcl_ip() {
+ declare -g if="$(getarg BOOTIF=)"
+ if [ -n "$if" ] && [ ${#if} -eq 20 ]; then
+ if="${if#???}"
+ if="${if//-/:}"
fi
- readonly BOOTIF
-
- ## KCL "ip": is expected in following format (syslinux IPAPPEND3):
- declare -rg IPCONF="$(getarg ip=)"
- # <CLIENT_IP>:<PXE_SERVER_IP>:<GATEWAY_IP>:<NETMASK>
- declare -g CLIENT_IP=
- declare -g SERVER_IP=
- declare -g GATEWAY_IP=
- declare -g NETMASK=
- read -r CLIENT_IP SERVER_IP GATEWAY_IP NETMASK \
- <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${IPCONF}" )
- readonly CLIENT_IP SERVER_IP GATEWAY_IP NETMASK
-
- # Calculate routing prefix from netmask
- declare -rg ROUTING_PREFIX="$(ipcalc -s -p "$CLIENT_IP" "$NETMASK")"
-
- # KCL "hostname"
- declare -rg HOSTNAME="$(getarg hostname=)"
- [ -n "$HOSTNAME" ] && echo "$HOSTNAME" > /proc/sys/kernel/hostname
-
- # KCL "dns"
- declare -rg DNS="$(getarg dns=)"
-
- # KCL "domain"
- declare -rg DOMAIN="$(getarg domain=)"
-
- # VLAN tag
- declare -rg VLAN="$(getarg vlan=)"
- if [ -n "$VLAN" ]; then
- modprobe 8021q || warn "VLAN mode detected but failed to load 8021q!"
+ local ip_line="$(getarg ip=)"
+ [ -z "$ip_line" ] && return 0
+ read -r ip bootsrv router subnet \
+ <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${ip_line}" )
+ declare -g ip bootsrv router subnet
+}
+
+# parse new style 'ipv4.*=...' parameters
+parse_kcl_ipv4() {
+ for param in ip router dns hostname domain search if ntpsrv subnet; do
+ echo "Getting $param..."
+ local current="$(getarg ipv4.${param}=)"
+ [ -z "$current" ] && continue
+ declare -g "${param}=${current}"
+ done
+}
+
+parse_kcl() {
+ # we assume (and we should) that both variants contain the
+ # same information if they are present simultaneously.
+ parse_kcl_ip
+ parse_kcl_ipv4
+
+ # if not boot server was given, use slxsrv
+ if [ -z "$bootsrv" ]; then
+ kclsrv="$(getarg slxsrv=)"
+ [ -n "$kclsrc" ] && bootsrv="$kclsrv"
fi
- # Bridged mode?
- grep -wqE 'bridged' /proc/cmdline && declare -rg BRIDGED="y"
+ # calculate network mask
+ declare -g mask="$(ipcalc -s -p "$ip" "$subnet" | sed 's/.*=//')"
+
+ # vlan specified?
+ declare -g vlan="$(getarg vlan=)"
+
+ # Bridged the boot interface?
+ grep -wqE 'bridged' /proc/cmdline && declare -g bridged="y"
+
+ # backwards compat for old style hostname/dns/domain
+ for conf in hostname dns domain; do
+ conf_value="$(getarg ${conf}=)"
+ if [ -n "$conf_value" ]; then
+ declare -g "${conf}=${conf_value}"
+ fi
+ done
}
save_network_config() {
- cat <<-EOF > "${RUNTIME_CONF}"
- SLX_PXE_CLIENT_IP='${CLIENT_IP}'
- SLX_PXE_SERVER_IP='${SERVER_IP}'
- SLX_PXE_GATEWAY='${GATEWAY_IP}'
- SLX_PXE_NETMASK='${NETMASK}'
- SLX_PXE_MAC='${BOOTIF}'
- SLX_PXE_NETIF='${BOOTIF_NAME}'
- SLX_PXE_DNS='${DNS}'
- SLX_PXE_HOSTNAME='${HOSTNAME}'
- SLX_PXE_DOMAIN='${DOMAIN}'
- SLX_BRIDGE='${BRIDGED:+${BRIDGE_NAME}}'
- SLX_VLAN_ID='${VLAN}'
+ declare -rg network_conf="/run/openslx/network.conf"
+ mkdir -p "${network_conf%/*}"
+ cat <<-EOF > "$network_conf"
+ SLX_PXE_CLIENT_IP='$ip'
+ SLX_PXE_SERVER_IP='$bootsrv'
+ SLX_PXE_GATEWAY='$router'
+ SLX_PXE_NETMASK='$mask'
+ SLX_PXE_SUBNET='$subnet'
+ SLX_PXE_MAC='$if'
+ SLX_PXE_NETIF='$bootif_name'
+ SLX_PXE_DNS='${dns//,/ }'
+ SLX_PXE_HOSTNAME='$hostname'
+ SLX_PXE_DOMAIN='${search//,/ }'
+ SLX_PXE_NTP='${ntpsrv//,/ }'
+ SLX_BRIDGE='${bridged:+${bridge_name}}'
+ SLX_VLAN_ID='$vlan'
EOF
}
# Create udev rule to rename the PXE boot interface to BOOTIF_NAME
create_udev_bootif_name_rule() {
- if [ -z "${BOOTIF}" ]; then
- echo "No BOOTIF set, was it present in the kernel command line?"
+ if [ -z "$if" ]; then
+ echo "MAC address of boot interface not set!"
return 1
fi
# priority 70 < 80-net-name-slot.rules.
- echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'${BOOTIF}'", NAME="'${BOOTIF_NAME}'"' > /etc/udev/rules.d/70-pxe-boot-interface.rules
+ echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'$if'", NAME="'$bootif_name'"' > /etc/udev/rules.d/70-pxe-boot-interface.rules
}
## MAIN ##
-# Get IP config from KCL
-parse_kernel_command_line
+parse_kcl
+
+# set hostname asap
+[ -n "$hostname" ] && echo "$hostname" > /proc/sys/kernel/hostname
# Save network config for later use
save_network_config &
@@ -91,5 +108,8 @@ save_network_config &
# Create the udev rule to rename the boot interface to the declared BOOTIF_NAME
create_udev_bootif_name_rule &
+wait
+
+# TODO handle case where the MAC address of the boot interface was not found
/sbin/initqueue --settled /usr/local/bin/setup-bootif-network
/sbin/initqueue --finished [ -e "/.network" ]
diff --git a/modules.d/slx-network/scripts/setup-bootif-network.stage3 b/modules.d/slx-network/scripts/setup-bootif-network.stage3
index 50718894..74d1c2b5 100755
--- a/modules.d/slx-network/scripts/setup-bootif-network.stage3
+++ b/modules.d/slx-network/scripts/setup-bootif-network.stage3
@@ -80,14 +80,26 @@ if [ -n "$SLX_BRIDGE" ]; then
done
fi
-# finally add the IP address on the main NIC
-if [ -n "$SLX_PXE_CLIENT_IP" ]; then
- ip addr add \
- "${SLX_PXE_CLIENT_IP}/$(ipcalc -s -p "$SLX_PXE_CLIENT_IP" "$SLX_PXE_NETMASK" | sed "s/.*=//")" \
- broadcast "$(ipcalc -s -b "$SLX_PXE_CLIENT_IP" "$SLX_PXE_NETMASK" | sed "s/.*=//")" \
- dev "$MAIN_NETIF"
+# Finally add the IP address on the main NIC.
+# Note: we should never have ip & netmask without the other.
+if [ -n "$SLX_PXE_CLIENT_IP" ] && [ -n "$SLX_PXE_NETMASK" ]; then
+ ip addr add "${SLX_PXE_CLIENT_IP}/${SLX_PXE_NETMASK}" dev "$MAIN_NETIF"
+
+ # now if we got everything from the KCL and skip dhcp if so
+ if [ -n "$SLX_PXE_GATEWAY" ] && [ -n "$SLX_PXE_DNS" ]; then
+ info "Got network configuration from KCL, skipping DHCP."
+ if ! interface="$MAIN_NETIF" \
+ ip="$SLX_PXE_CLIENT_IP" \
+ router="$SLX_PXE_GATEWAY" \
+ dns="$SLX_PXE_DNS" \
+ /usr/local/bin/udhcpc-trigger bound; then
+ warn "Failed to launch DHCP trigger with KCL configuration - will DHCP."
+ fi
+ exit 0
+ fi
fi
+## DHCP
additional_opts=()
# we need to send the same UID (without '-') as the PXE firmware did, so use the plain
@@ -106,6 +118,7 @@ fi
# DHCP options to request
request_opts=("-O" "hostname")
+request_opts+=("-O" "dns")
request_opts+=("-O" "ntpsrv")
request_opts+=("-O" "domain")
request_opts+=("-O" "wpad")
@@ -131,3 +144,4 @@ set +x
} &>> "/run/openslx/initramfs-network.log.$$"
+
diff --git a/modules.d/slx-network/scripts/udhcpc-trigger.stage3 b/modules.d/slx-network/scripts/udhcpc-trigger.stage3
index d54939a8..27c0f22a 100755
--- a/modules.d/slx-network/scripts/udhcpc-trigger.stage3
+++ b/modules.d/slx-network/scripts/udhcpc-trigger.stage3
@@ -32,26 +32,25 @@ if [ -n "$SLX_PXE_CLIENT_IP" ]; then
#...some address is already configured...
if [ "x${SLX_PXE_CLIENT_IP}" != "x${ip}" ]; then
#...it's a different one, reconfigure...
- echo "..reconfiguring ${SLX_PXE_CLIENT_IP} to ${ip}.."
+ echo "..reconfiguring '${SLX_PXE_CLIENT_IP}' to '${ip}'."
# remove default route and let it be added again below, as it might get lost when changing the primary address on the interface
ip route del default 2>/dev/null
ip addr del "$SLX_PXE_CLIENT_IP" dev "${interface}" 2>/dev/null
ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}"
+ echo "SLX_DHCP_CLIENT_IP='$ip'" >> "$NETWORK_CONF"
fi
else
#...no address configured yet, just add...
echo "..adding ${ip}.."
ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}"
fi
-echo "SLX_DHCP_CLIENT_IP='$ip'" >> "$NETWORK_CONF"
# Same procedure for default gateway
-if [ -n "${router}" ]; then
- if [ -s "$SLX_PXE_GATEWAY" ]; then
- if [ "x${SLX_PXE_GATEWAY}" != "x${router}" ]; then
- echo "..reconfiguring default gw from ${SLX_PXE_GATEWAY} to ${router}.."
- ip route replace default via "$router"
- fi
+if [ -n "$router" ]; then
+ if [ -n "$SLX_PXE_GATEWAY" ] && [ "$SLX_PXE_GATEWAY" != "$router" ]; then
+ echo "..reconfiguring default gw from '$SLX_PXE_GATEWAY' to '$router'."
+ ip route del default 2>/dev/null
+ ip route add default via "$router"
else
ip route add default via "$router"
fi
@@ -65,21 +64,30 @@ fi
rm -f -- "/etc/resolv.conf"
+reverse_lookup() {
+ [ -z "$dns" ] && return
+ [ -z "$1" ] && return
+ timeout -t 3 nslookup "$1" | grep -E "^Address +[0-9]+: +$1 " | head -n 1 | awk '{print $4}'
+}
+
+echo "# From DHCP in stage 3.1" >> "$NETWORK_CONF"
+
# DNS/domain?
if [ -n "$dns" ]; then
echo "..got DNS.."
- echo "# From DHCP in stage 3.1" >> "$NETWORK_CONF"
echo "SLX_DNS='$dns'" >> "$NETWORK_CONF"
fi
for srv in $dns; do
echo "nameserver $srv" >> "/etc/resolv.conf"
done
+
if [ -z "$domain" ]; 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}')
+ fqdn="$(reverse_lookup "$ip")"
domain="${fqdn#*.}"
fi
+
# Add domain to list of search domains if not in there yet
if [ -n "$domain" ] && [ -n "$search" ]; then
FOUND=no
@@ -90,11 +98,13 @@ if [ -n "$domain" ] && [ -n "$search" ]; then
elif [ -n "$domain" ]; then
search="$domain"
fi
+
# Write out
if [ -n "$domain" ]; then
echo "domain $domain" >> "/etc/resolv.conf"
echo "SLX_NET_DOMAIN='$domain'" >> "/run/openslx/network.conf"
fi
+
if [ -n "$search" ]; then
echo "search $search" >> "/etc/resolv.conf"
echo "SLX_NET_SEARCH='$search'" >> "/run/openslx/network.conf"
@@ -113,7 +123,7 @@ else
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" ] && fqdn="$(reverse_lookup "$ip")"
hostname="${fqdn%%.*}"
elif [ -n "$domain" ]; then
fqdn="${hostname}.${domain%% *}" # in case domain is a list
@@ -132,7 +142,7 @@ if [ -n "$hostname" ]; then
echo "$hostname" > "/etc/hostname"
echo "127.0.0.1 localhost" > "/etc/hosts"
echo "127.0.1.1 $fqdn $hostname" >> "/etc/hosts"
- echo "SLX_HOSTNAME='$hostname'" >> "/run/openslx/network.conf"
+ echo "SLX_HOSTNAME='$hostname'" >> "$NETWORK_CONF"
fi
touch /.network