diff --git a/modules.d/40network/net-genrules.sh b/modules.d/40network/net-genrules.sh index 0768975e..3d504351 100755 --- a/modules.d/40network/net-genrules.sh +++ b/modules.d/40network/net-genrules.sh @@ -15,12 +15,20 @@ fix_bootif() { # Write udev rules { -# BOOTIF says everything, use only that one + # BOOTIF says everything, use only that one BOOTIF=$(getarg 'BOOTIF=') if [ -n "$BOOTIF" ] ; then BOOTIF=$(fix_bootif "$BOOTIF") printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$BOOTIF" - else + + # If we have to handle multiple interfaces, handle only them. + elif [ -n "$IFACES" ] ; then + for iface in $IFACES ; do + printf 'ACTION=="add", SUBSYSTEM=="net", KERNEL=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$iface" + done + + # Default: We don't know the interface to use, handle all + else printf 'ACTION=="add", SUBSYSTEM=="net", RUN+="/sbin/ifup $env{INTERFACE}"\n' fi diff --git a/modules.d/40network/netroot b/modules.d/40network/netroot index d860c6a4..dce18b08 100755 --- a/modules.d/40network/netroot +++ b/modules.d/40network/netroot @@ -30,7 +30,17 @@ fi [ -d $NEWROOT/proc ] && exit 0 [ -z "$netroot" ] && exit 1 +# Let's see if we have to wait for other interfaces +# Note: exit works just fine, since the last interface to be +# online'd should see all files +[ -e "/tmp/net.ifaces" ] && read IFACES < /tmp/net.ifaces +for iface in $IFACES ; do + [ -e /tmp/net.$iface.up ] || exit 1 +done + +# Set or override primary interface netif=$1 +[ -e "/tmp/net.bootdev" ] && read netif < /tmp/net.bootdev # Figure out the handler for root=dhcp by recalling all netroot cmdline # handlers @@ -41,6 +51,14 @@ if [ "$netroot" = "dhcp" ] ; then # Load dhcp options [ -e /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts + # If we have a specific bootdev with no dhcpoptions or empty root-path, + # we die. Otherwise we just warn + if [ -z "$new_root_path" ] ; then + [ -n "$BOOTDEV" ] && die "No dhcp root-path received for '$BOOTDEV'" + warn "No dhcp root-path received for '$BOOTDEV' trying other interfaces if available" + exit 1 + fi + # Set netroot to new_root_path, so cmdline parsers don't call netroot=$new_root_path @@ -63,7 +81,11 @@ if [ -z "$netroot" ] || [ ! -e "$handler" ] ; then fi # We're here, so we can assume that upping interfaces is now ok -. /tmp/net.$netif.up +[ -z "$IFACES" ] && IFACES="$netif" +for iface in $IFACES ; do + . /tmp/net.$iface.up +done + [ -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 @@ -75,17 +97,21 @@ source_all netroot # XXX other variables to export? if $handler $netif $netroot $NEWROOT; then # Network rootfs mount successful - [ -f /tmp/dhclient.$netif.lease ] && cp /tmp/dhclient.$netif.lease /tmp/net.$netif.lease - [ -f /tmp/dhclient.$netif.dhcpopts ] && cp /tmp/dhclient.$netif.dhcpopts /tmp/net.$netif.dhcpopts + for iface in $IFACES ; do + [ -f /tmp/dhclient.$iface.lease ] && cp /tmp/dhclient.$iface.lease /tmp/net.$iface.lease + [ -f /tmp/dhclient.$iface.dhcpopts ] && cp /tmp/dhclient.$iface.dhcpopts /tmp/net.$iface.dhcpopts + done # Save used netif for later use - echo $netif > /tmp/net.bootdev + [ ! -f /tmp/net.ifaces ] && echo $netif > /tmp/net.ifaces 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 + if [ -z "$BOOTDEV" ] ; then + ip link set $netif down + ip addr flush dev $netif + echo "#empty" > /etc/resolv.conf + fi fi exit 0 diff --git a/modules.d/40network/parse-ip-opts.sh b/modules.d/40network/parse-ip-opts.sh index 4a3de342..c748fdf1 100755 --- a/modules.d/40network/parse-ip-opts.sh +++ b/modules.d/40network/parse-ip-opts.sh @@ -7,6 +7,10 @@ # # ip=::::::[dhcp|on|any|none|off] # +# When supplying more than only ip= line, is mandatory and +# bootdev= must contain the name of the primary interface to use for +# routing,dns,dhcp-options,etc. +# # Sadly there's no easy way to split ':' separated lines into variables ip_to_var() { @@ -47,6 +51,22 @@ if [ -n "$netroot" ] && [ -z "$(getarg ip=)" ] ; then return; fi +# Count ip= lines to decide whether we need bootdev= or not +if [ -z "$NEEDBOOTDEV" ] ; then + [ "$CMDLINE" ] || read CMDLINE < /proc/cmdline + local count=0 + for p in $CMDLINE; do + [ "${p%%=*}" = "ip" ] && count=$(( $count + 1 )) + done + [ $count -gt 1 ] && NEEDBOOTDEV=1 +fi + +# If needed, check if bootdev= contains anything usable +if [ -n "$NEEDBOOTDEV" ] ; then + BOOTDEV=$(getarg bootdev=) || die "Please supply bootdev argument for multiple ip= lines" + [ -z "$BOOTDEV" ] && die "Bootdev argument is empty" +fi + # Check ip= lines # XXX Would be nice if we could errorcheck ip addresses here as well [ "$CMDLINE" ] || read CMDLINE < /proc/cmdline @@ -55,6 +75,9 @@ for p in $CMDLINE; do ip_to_var ${p#ip=} + # We need to have an ip= line for the specified bootdev + [ -n "$NEEDBOOTDEV" ] && [ "$dev" = "$BOOTDEV" ] && BOOTDEVOK=1 + # Empty autoconf defaults to 'dhcp' if [ -z "$autoconf" ] ; then warn "Empty autoconf values default to dhcp" @@ -72,34 +95,52 @@ for p in $CMDLINE; do die "Sorry, automatic calculation of netmask is not yet supported" ;; dhcp|on|any) \ + [ -n "$NEEDBOOTDEV" ] && [ -z "$dev" ] && \ + die "Sorry, '$p' does not make sense for multiple interface configurations" [ -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 + # We don't like duplicate device configs if [ -n "$IFACES" ] ; then for i in $IFACES ; do [ "$dev" = "$i" ] && die "For argument '$p'\nDuplication configurations for '$dev'" done fi + # IFACES list for later use 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" + # Small optimization for udev rules + [ -z "$NEEDBOOTDEV" ] && [ -n "$dev" ] && BOOTDEV=$dev + + # Do we need to check for specific options? + if [ -n "$NEEDDHCP" ] || [ -n "$DHCPORSERVER" ] ; then + # Correct device? (Empty is ok as well) + [ "$dev" = "$BOOTDEV" ] || continue + # Server-ip is there? + [ -n "$DHCPORSERVER" ] && [ -n "$srv" ] && continue + # dhcp? (It's simpler to check for a set ip. Checks above ensure that if + # ip is there, we're static + [ -z "$ip" ] && continue + # Not good! + die "Server-ip or dhcp for netboot needed, but current arguments say otherwise" fi done -[ -n "$NEEDDHCP" ] && [ -z "$DHCPOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise" +# This ensures that BOOTDEV is always first in IFACES +if [ -n "$BOOTDEV" ] && [ -n "$IFACES" ] ; then + IFACES="${IFACES%$BOOTDEV*} ${IFACES#*$BOOTDEV}" + IFACES="$BOOTDEV $IFACES" +fi + +# Store BOOTDEV and IFACES for later use +[ -n "$BOOTDEV" ] && echo $BOOTDEV > /tmp/net.bootdev +[ -n "$IFACES" ] && echo $IFACES > /tmp/net.ifaces -[ -n "$DHCPORSERVER" ] && [ -z "$SRVOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise" +# We need a ip= line for the configured bootdev= +[ -n "$NEEDBOOTDEV" ] && [ -z "$BOOTDEVOK" ] && die "Bootdev Argument '$BOOTDEV' not found" \ No newline at end of file diff --git a/modules.d/40network/write-ifcfg.sh b/modules.d/40network/write-ifcfg.sh index e5f25d57..c408076b 100755 --- a/modules.d/40network/write-ifcfg.sh +++ b/modules.d/40network/write-ifcfg.sh @@ -1,23 +1,25 @@ #!/bin/sh # Don't write anything if we don't know our bootdev -[ -f /tmp/net.bootdev ] || return 1 +[ -f /tmp/net.ifaces ] || return 1 -read netif < /tmp/net.bootdev +read IFACES < /tmp/net.ifaces -cat /sys/class/net/$netif/address > /tmp/net.$netif.hwaddr -echo "# Generated by dracut initrd" > /tmp/net.$netif.ifcfg -echo "DEVICE=$netif" >> /tmp/net.$netif.ifcfg -echo "HWADDR=$(cat /sys/class/net/$netif/address)" >> /tmp/net.$netif.ifcfg -echo "TYPE=Ethernet" >> /tmp/net.$netif.ifcfg -echo "ONBOOT=yes" >> /tmp/net.$netif.ifcfg -if [ -f /tmp/net.$netif.lease ]; then - echo "BOOTPROTO=dhcp" >> /tmp/net.$netif.ifcfg -else - echo "BOOTPROTO=none" >> /tmp/net.$netif.ifcfg - # If we've booted with static ip= lines, the override file is there - . /tmp/net.$netif.override - echo "IPADDR=$ip" >> /tmp/net.$netif.ifcfg - echo "NETMASK=$mask" >> /tmp/net.$netif.ifcfg - [ -n "$gw" ] && echo "GATEWAY=$gw" >> /tmp/net.$netif.ifcfg -fi +for netif in $IFACES ; do + cat /sys/class/net/$netif/address > /tmp/net.$netif.hwaddr + echo "# Generated by dracut initrd" > /tmp/net.$netif.ifcfg + echo "DEVICE=$netif" >> /tmp/net.$netif.ifcfg + echo "HWADDR=$(cat /sys/class/net/$netif/address)" >> /tmp/net.$netif.ifcfg + echo "TYPE=Ethernet" >> /tmp/net.$netif.ifcfg + echo "ONBOOT=yes" >> /tmp/net.$netif.ifcfg + if [ -f /tmp/net.$netif.lease ]; then + echo "BOOTPROTO=dhcp" >> /tmp/net.$netif.ifcfg + else + echo "BOOTPROTO=none" >> /tmp/net.$netif.ifcfg + # If we've booted with static ip= lines, the override file is there + . /tmp/net.$netif.override + echo "IPADDR=$ip" >> /tmp/net.$netif.ifcfg + echo "NETMASK=$mask" >> /tmp/net.$netif.ifcfg + [ -n "$gw" ] && echo "GATEWAY=$gw" >> /tmp/net.$netif.ifcfg + fi +done