netroot: Add ip= cmdline checker
authorPhilippe Seewer <philippe.seewer@bfh.ch>
Tue, 16 Jun 2009 17:14:51 +0000 (19:14 +0200)
committerPhilippe Seewer <philippe.seewer@bfh.ch>
Wed, 17 Jun 2009 06:37:40 +0000 (08:37 +0200)
As with other netroot boot arguments ip= lines should be parsed and
checked. Having this has the advantage that other cmdline scripts
can tell the ip= parser if dhcp or ip=:srv:... is needed, like
parse-root.sh (renamed dhcp-fallback) or parse-nfsroot do.

The nfs test-suite has one check which uses static ip lines, but
the autoconf param is wrong. Fixed this as well.

modules.d/40network/dhcp-fallback.sh [deleted file]
modules.d/40network/dhcp-root.sh [new file with mode: 0755]
modules.d/40network/install
modules.d/40network/parse-ip-opts.sh [new file with mode: 0755]
modules.d/95nfs/parse-nfsroot.sh
test/TEST-20-NFS/test.sh

diff --git a/modules.d/40network/dhcp-fallback.sh b/modules.d/40network/dhcp-fallback.sh
deleted file mode 100755 (executable)
index 7843640..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# We should go last, and default the root if needed
-
-if [ -z "$root" -a -z "$netroot" ]; then
-    rootok=1
-    root=dhcp
-    netroot=dhcp
-fi
-
-if [ "$root" = "dhcp" -a -z "$netroot" ]; then
-    rootok=1
-    netroot=dhcp
-fi
-
-if [ "$netroot" = "dhcp" -a -z "$root" ]; then
-    rootok=1
-    root=dhcp
-fi
-
-if [ -n "$NEEDDHCP" ] ; then
-    rootok=1
-    root=dhcp
-    #Don't overwrite netroot here, as it might contain something useful
-fi
diff --git a/modules.d/40network/dhcp-root.sh b/modules.d/40network/dhcp-root.sh
new file mode 100755 (executable)
index 0000000..c00ba06
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# Don't continue if root is ok
+[ -n "$rootok" ] && return
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+[ -z "$netroot" ] && netroot=$(getarg netroot=)
+
+if [ "$root" = "dhcp" ] || [ "$netroot" = "dhcp" ] ; then
+    # Tell ip= checker that we need dhcp
+    NEEDDHCP="1"
+
+    # Done, all good!
+    rootok=1
+    netroot=dhcp
+
+    # Shut up init error check
+    [ -z "$root" ] && root="dhcp"
+fi
index 2e381e2..cb9359e 100755 (executable)
@@ -16,7 +16,8 @@ inst "$moddir/dhclient-script" "/sbin/dhclient-script"
 inst "$moddir/dhclient.conf" "/etc/dhclient.conf" 
 instmods ecb arc4
 inst_rules "$moddir/60-net.rules"
-inst_hook cmdline 99 "$moddir/dhcp-fallback.sh"
+inst_hook cmdline 91 "$moddir/dhcp-root.sh"
+inst_hook cmdline 99 "$moddir/parse-ip-opts.sh"
 inst_hook pre-pivot 10 "$moddir/kill-dhclient.sh"
 
 # TODO ifcfg config style is redhat specific, this should probably
diff --git a/modules.d/40network/parse-ip-opts.sh b/modules.d/40network/parse-ip-opts.sh
new file mode 100755 (executable)
index 0000000..df1a071
--- /dev/null
@@ -0,0 +1,90 @@
+#!/bin/sh
+#
+# Format:
+#      ip=[dhcp|on|any]
+#
+#      ip=<interface>:[dhcp|on|any]
+#
+#      ip=<client-IP-number>:<server-id>:<gateway-IP-number>:<netmask>:<client-hostname>:<interface>:[dhcp|on|any|none|off]
+#
+
+# Sadly there's no easy way to split ':' separated lines into variables
+ip_to_var() {
+    local v=${1}:
+    set --
+    while [ -n "$v" ]; do
+       set -- "$@" "${v%%:*}"
+       v=${v#*:}
+    done
+
+    unset ip srv gw mask hostname dev autoconf
+    case $# in
+    0) autoconf="error" ;;
+    1) autoconf=$1 ;;
+    2) dev=$1; autoconf=$2 ;;
+    *) ip=$1; srv=$2; gw=$3; mask=$4; hostname=$5; dev=$6; autoconf=$7 ;;
+    esac
+}
+
+# Warn if defaulting to ip=dhcp
+if [ -n "$netroot" ] && [ -z "$(getarg ip=)" ] ; then
+    warn "No ip= argument(s) for netroot provided, defaulting to DHCP"
+    return;
+fi
+
+# Check ip= lines
+# XXX Would be nice if we could errorcheck ip addresses here as well
+[ "$CMDLINE" ] || read CMDLINE < /proc/cmdline
+for p in $CMDLINE; do
+    [ -n "${p%ip=*}" ] && continue
+
+    ip_to_var ${p#ip=}
+
+    # Empty autoconf defaults to 'dhcp'
+    if [ -z "$autoconf" ] ; then
+       warn "Empty autoconf values default to dhcp"
+       autoconf="dhcp"
+    fi
+
+    # Error checking for autoconf in combination with other values
+    case $autoconf in
+       error) die "Error parsing option '$p'";;
+       bootp|rarp|both) die "Sorry, ip=$autoconf is currenty unsupported";;
+       none|off) \
+           [ -z "$ip" ] && \
+               die "For argument '$p'\nValue '$autoconf' without static configuration does not make sense"
+           [ -z "$mask" ] && \
+               die "Sorry, automatic calculation of netmask is not yet supported"
+           ;;
+       dhcp|on|any) \
+           [ -n "$ip" ] && \
+               die "For argument '$p'\nSorry, setting client-ip does not make sense for '$autoconf'"
+           ;;
+       *) die "For argument '$p'\nSorry, unknown value '$autoconf'";;
+    esac
+
+    # We don't like duplicate device configs
+    if [ -n "$dev" ] ; then
+       if [ -n "$IFACES" ] ; then
+           for i in $IFACES ; do
+               [ "$dev" = "$i" ] && die "For argument '$p'\nDuplication configurations for '$dev'"
+           done
+       fi
+       IFACES="$IFACES $dev"
+    fi
+
+    # Do we need DHCP? (It's simpler to check for a set ip. Checks above ensure that if
+    # ip is there, we're static) 
+    [ -n "$NEEDDHCP" ] && [ -z "$ip" ] && DHCPOK="1"
+
+    # Do we need srv OR dhcp?
+    if [ -n "$DHCPORSERVER" ] ; then
+       [ -n "$DHCPOK" ] && SRVOK="1"
+       [ -n "$srv" ] && SRVOK="1"
+    fi
+
+done
+
+[ -n "$NEEDDHCP" ] && [ -z "$DHCPOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise"
+
+[ -n "$DHCPORSERVER" ] && [ -z "$SRVOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise"
index d47be9e..0a74288 100755 (executable)
@@ -125,7 +125,7 @@ netroot="$fstype:$server:$path:$options"
 
 # If we don't have a server, we need dhcp
 if [ -z "$server" ] ; then
-    NEEDDHCP="1"
+    DHCPORSERVER="1"
 fi;
 
 # Done, all good!
index 7dc3245..0f1f36c 100755 (executable)
@@ -164,7 +164,7 @@ test_nfsv3() {
     client_test "NFSv3 root=nfs nfsroot=/nfs/ip/%s no host name (use IP)" \
        52:54:00:12:34:7f \
        "root=nfs nfsroot=/nfs/ip/%s \
-               ip=192.168.50.101:192.168.50.1::255.255.255.0::eth0:static" \
+               ip=192.168.50.101:192.168.50.1::255.255.255.0::eth0:off" \
        192.168.50.1 -wsize=4096 || return 1
 
     client_test "NFSv3 root=nfs nfsroot=/nfs/client,wsize=4096" \