multnic support: move actual interface configuration to netroot
authorPhilippe Seewer <philippe.seewer@bfh.ch>
Tue, 16 Jun 2009 18:21:41 +0000 (20:21 +0200)
committerPhilippe Seewer <philippe.seewer@bfh.ch>
Wed, 17 Jun 2009 06:37:40 +0000 (08:37 +0200)
Instead of configuring devices when they are ready, ifup and
dhclient-script write script files which are then sourced by
netroot.

This solves the problem of having multiple interfaces and not knowing
which one to use for dhcp or default route. This way, netroot (which
is serialized anyway) configures the interface before calling the root
handler and deconfigures it if the handler failed.

Example: root=nfs:server:path and ip=dhcp with eth0 and eth1 receiving
a dhcp reply, but eth0 is the correct one to use.

Assuming eth1 is the first to receive the dhcp-reply, netroot starts
and configures eth1. nfsroot is run but fails, so eth1 is deconfigured. If
eth0 has received a dhcp-reply (or not, then we wait) the other locked
netroot process starts and tries with eth0 and succeeds.

modules.d/40network/dhclient-script
modules.d/40network/ifup
modules.d/40network/netroot

index 3a255de..80ab54c 100755 (executable)
@@ -1,22 +1,4 @@
 #!/bin/sh -e
-# very simple dhclient-script.  All it cares about is bringing the interface
-# up, and it does not even try to do anything else.
-
-LOG=/tmp/dhclient.$$.log
-ERR=/tmp/network.$$.err
-
-log_err() {
-    # avoid the need for cat on the image
-    echo "On $netif, the following command:" > $ERR
-    echo "    " "$CMD" >> $ERR
-    echo "had errors:" >> $ERR
-    while read line; do echo "     $line"; done < $LOG >> $ERR
-}
-
-run() {
-    CMD="$@"
-    "$@" >> $LOG 2>&1
-}
 
 setup_interface() {
     ip=$new_ip_address
@@ -32,23 +14,23 @@ setup_interface() {
     [ -f /tmp/net.$netif.override ] && . /tmp/net.$netif.override
 
     if [ -n "$mtu" ] ; then
-       run ip link set $netif down
-       run ip link set $netif mtu $mtu
-       run ip link set $netif up
-    fi
+       echo ip link set $netif down
+       echo ip link set $netif mtu $mtu
+       echo ip link set $netif up
+    fi > /tmp/net.$netif.up
 
-    run ip addr add $ip${mask:+/$mask} ${bcast:+broadcast $bcast} dev $netif
-    [ -n "$gw" ] && run ip route add default via $gw
-    if [ -n "${search}${domain}" -a -n "$namesrv" ] ; then
-       echo search $search $domain > /etc/resolv.conf
+    echo ip addr add $ip${mask:+/$mask} ${bcast:+broadcast $bcast} dev $netif >> /tmp/net.$netif.up
+
+    [ -n "$gw" ] && echo ip route add default via $gw dev $netif > /tmp/net.$netif.gw
+
+    [ -n "${search}${domain}" ] && echo search $search $domain > /tmp/net.$netif.resolv.conf
+    if  [ -n "$namesrv" ] ; then
        for s in $namesrv; do
-           echo nameserver $s >> /etc/resolv.conf
+           echo nameserver $s 
        done
-    fi
-    if [ ! -e /tmp/hostname.set ] ; then
-       [ -n "$hostname" ] && mknod /tmp/hostname.set p && run hostname $hostname
-    fi
-    :
+    fi >> /tmp/net.$netif.resolv.conf
+
+    [ -n "$hostname" ] && echo hostname $hostname > /tmp/net.$netif.hostname
 }
 
 PATH=$PATH:/sbin:/usr/sbin
@@ -64,15 +46,12 @@ fi
 # Huh? Interface configured?
 [ -f "/tmp/net.$netif.up" ] && exit 0
 
-# save offending commands and let udev move on if we have an error
-trap 'log_err; exit 0' EXIT
-
 # We already need a set netif here
 netif=$interface
 
 case $reason in
     PREINIT)
-       run ip link set $netif up
+       ip link set $netif up
        ;;
     BOUND)
        setup_interface 
@@ -80,10 +59,9 @@ case $reason in
            [ "${line#new_}" = "$line" ] && continue
            echo "$line" 
        done >/tmp/dhclient.$netif.dhcpopts
-       >/tmp/net.$netif.up
-       echo online > /sys/class/net/$netif/uevent ;;
+       echo online > /sys/class/net/$netif/uevent
+       ;;
     *) ;;
 esac
 
-trap - EXIT
 exit 0
index a1ad01e..fb381af 100755 (executable)
@@ -1,40 +1,47 @@
 #!/bin/sh
+#
+# We don't need to check for ip= errors here, that is handled by the
+# cmdline parser script
+#
+
+# 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
 
-die() {
-    echo $netif: "$@" 1>&2
-    exit 1
-}
-
-do_static() {
-    [ -n "$ip" ] || die "static: need IP address"
-    [ -n "$mask" ] || {
-       net=${ip%%.*}
-       mask=255.0.0.0
-       [ $net -ge 128 ] && mask=255.255.0.0
-       [ $net -ge 192 ] && mask=255.255.255.0
-    }
-    ip addr add $ip/$mask dev $netif || die "static: setting IP $ip/$mask"
-    [ -n "$gw" ] && {
-       ip route add default via $gw dev $netif ||
-           die "static: setting default route via $gw"
-    }
-    ip link set $netif up 
-    [ -e /tmp/hostname.set ] || {
-       [ -n "$hostname" ] && mknod /tmp/hostname.set p 2>/dev/null &&
-           hostname $hostname
-    }
-    [ -n "$srv" ] &&
-       echo "new_dhcp_server_identifier=$srv" > /tmp/dhclient.$netif.dhcpopts
-
-    >/tmp/net.$netif.up
-    echo online > /sys/class/net/$netif/uevent
+    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
 }
 
+# Run dhclient
 do_dhcp() {
     # /sbin/dhclient-script will mark the netif up and generate the online
     # event for nfsroot
     # XXX add -V vendor class and option parsing per kernel
-    dhclient -1 -q -cf /etc/dhclient.conf -pf /tmp/dhclient.$netif.pid -lf /tmp/dhclient.$netif.lease $netif
+    dhclient -1 -q -cf /sbin/dhclient.conf -pf /tmp/dhclient.$netif.pid -lf /tmp/dhclient.$netif.lease $netif
+}
+
+# Handle static ip configuration
+do_static() {
+{
+       echo ip link set $netif up 
+       echo ip addr flush dev $netif
+       echo ip addr add $ip/$mask dev $netif
+    } > /tmp/net.$netif.up
+
+    [ -n "$gw" ] && echo ip route add default via $gw dev $netif > /tmp/net.$netif.gw
+    [ -n "$hostname" ] && echo hostname $hostname > /tmp/net.$netif.hostname
+
+    echo online > /sys/class/net/$netif/uevent
 }
 
 PATH=$PATH:/sbin:/usr/sbin
@@ -82,7 +89,7 @@ for p in $CMDLINE; do
     ip_to_var ${p#ip=}
        
     # If this option isn't directed at our interface, skip it
-    [ "$dev" = "$netif" ] || continue
+    [ -n "$dev" ] && [ "$dev" != "$netif" ] && continue
 
     # Store config for later use
     for i in ip srv gw mask hostname; do
@@ -90,12 +97,9 @@ for p in $CMDLINE; do
     done > /tmp/net.$netif.override
 
     case $autoconf in
-       static)          do_static ;;
        dhcp|on|any)     do_dhcp ;;
-       bootp|rarp|both) die "autoconfig type $autoconf is not supported" ;;
-       ''|none|off)     ;;
-       esac
-       break
-    done
-fi
+        *) do_static ;;
+    esac
+    break
+done
 exit 0
index b35c6c4..d860c6a 100755 (executable)
@@ -62,6 +62,12 @@ if [ -z "$netroot" ] || [ ! -e "$handler" ] ; then
     die "No handler for netroot type '$netroot'"
 fi
 
+# We're here, so we can assume that upping interfaces is now ok
+. /tmp/net.$netif.up
+[ -e /tmp/net.$netif.gw ]          && . /tmp/net.$netif.gw
+[ -e /tmp/net.$netif.hostname ]    && . /tmp/net.$netif.hostname
+[ -e /tmp/net.$netif.resolv.conf ] && cp -f /tmp/net.$netif.resolv.conf /etc/resolv.conf
+
 # Source netroot hooks before we start the handler
 source_all netroot
 
@@ -74,5 +80,12 @@ if $handler $netif $netroot $NEWROOT; then
 
     # Save used netif for later use
     echo $netif > /tmp/net.bootdev
+else 
+    warn "Mounting root via '$netif' failed"
+    # If we're trying with multiple interfaces, put that one down.
+    # ip down/flush ensures that routeing info goes away as well
+    ip link set $netif down
+    ip addr flush dev $netif
+    echo "#empty" > /etc/resolv.conf
 fi
 exit 0