[RFC PATCH 4/5] network: prepare network configuration engine for udev-based nfsroot

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This changes the network config to run dhclient from within udev, and
allows multiple dhclients to run at once. It also sets the hostname and
adds a kernel command line option 'netdebug' to help debug network issues.

This an RFC patch, as I've not tested it since porting to the current
dracut (it worked in HEAD as of April, though).
---
 modules.d/40network/dhclient-script  |   98 ++++++++++++++++----
 modules.d/40network/ifup             |  124 +++++++++++++++++++++-----
 modules.d/40network/install          |    3 +-
 modules.d/40network/kill-dhclient.sh |    5 +-
 modules.d/40network/run-dhclient.sh  |    9 --
 5 files changed, 182 insertions(+), 57 deletions(-)

diff --git a/modules.d/40network/dhclient-script b/modules.d/40network/dhclient-script
index 895ed1b..7689e04 100755
--- a/modules.d/40network/dhclient-script
+++ b/modules.d/40network/dhclient-script
@@ -1,27 +1,85 @@
-#!/bin/sh
+#!/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.
 
-case $reason in
-    PREINIT) /sbin/ip link set "$interface" up ;;
-    BOUND) ipopts="$new_ip_address"
-     	[ "$new_interface_mtu" ] && ip link set $interface mtu $new_interface_mtu
-	[ "$new_subnet_mask" ] && ipopts="$ipopts/$new_subnet_mask"
-	[ "$new_broadcast_address" ] && ipopts="$ipopts broadcast $new_broadcast_address"
-	/sbin/ip addr add $ipopts dev $interface
-	[ "$new_routers" ] && /sbin/ip route add default via ${new_routers%%,*} dev $interface
-	[ "$new_domain_name" ] && echo "domain $new_domain_name" > /etc/resolv.conf
-	if [ "$new_domain_search" ]; then
-	    echo "search $new_domain_search" |sed 's/,//g' >> /etc/resolv.conf
-	elif [ "$new_domain_name" ]; then
-	    echo "search $new_domain_name" >> /etc/resolv.conf
-	fi
-	for s in $new_domain_name_servers; do
-	    echo "nameserver $s" >> /etc/resolv.conf
+LOG=/dhclient.$$.log
+ERR=/network.$$.err
+PATH=$PATH:/sbin:/usr/sbin
+
+. /lib/dracut-lib
+
+getarg netdebug && {
+    exec >/dhclient.$interface.$$.out
+    exec 2>>/dhclient.$interface.$$.out
+    set -x
+}
+
+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
+}
+
+# Catch unlikely initial errors
+trap 'echo Errors preparing to configure $netif > $ERR; exit 0' EXIT
+
+netif=$interface
+ip=$new_ip_address
+mtu=$new_interface_mtu
+mask=$new_subnet_mask
+bcast=$new_broadcast_address
+gw=${new_routers%%,*}
+domain=$new_domain_name
+search=$new_domain_search
+namesrv=$new_domain_name_servers
+hostname=$new_host_name
+
+[ -f /net.$interface.override ] && . /net.$interface.override
+
+# save the offending command and let udev move on if we have an error
+trap 'log_err; exit 0' EXIT
+
+run() {
+    CMD="$@"
+    "$@" >> $LOG 2>&1
+}
+
+setup_interface() {
+    [ -n "$mtu" ] && {
+	run ip link set $netif down
+	run ip link set $netif mtu $mtu
+	run ip link set $netif up
+    }
+
+    run ip addr add $ip${mask:+/$mask} ${bcast:+broadcast $bcast} dev $netif
+    [ -n "$gw" ] && run ip route add default via $gw
+    [ -n "${search}${domain}" -a -n "$namesrv" ] && {
+	echo search $search $domain > /etc/resolv.conf
+	for s in $namesrv; do
+	    echo nameserver $s >> /etc/resolv.conf
 	done
-	set |grep -E '^new_[a-z_]+=' |while read line; do
-	    echo "${line%%=*}='${line#*=}'">>/net.$interface.dhcpopts
+    }
+    [ -e /hostname.set ] || {
+	[ -n "$hostname" ] && mknod /hostname.set p && run hostname $hostname
+    }
+}
+
+case $reason in
+    PREINIT)
+	run /sbin/ip link set $netif up
+	;;
+    BOUND)
+	setup_interface 
+	set | while read line; do
+	    [ "${line#new_}" = "$line" ] && continue
+	    echo "$line" >>/net.$netif.dhcpopts
 	done
-	>/net.$interface.up ;;
+	>/net.$netif.up
+	echo online > /sys/class/net/$netif/uevent ;;
     *) ;;
 esac
+
+trap - EXIT
+exit 0
diff --git a/modules.d/40network/ifup b/modules.d/40network/ifup
index 744a2ae..284c9df 100755
--- a/modules.d/40network/ifup
+++ b/modules.d/40network/ifup
@@ -1,36 +1,112 @@
 #!/bin/sh
 
+PATH=$PATH:/sbin:/usr/sbin
+
+. /lib/dracut-lib
+
+getarg netdebug && {
+    exec >/ifup.$1.$$.out
+    exec 2>>/ifup.$1.$$.out
+    set -x
+}
+
+netif=$1
+
 # bail immediatly if the interface is already up
-[ -f "/net.$1.up" ] && exit 0
+[ -f "/net.$netif.up" ] && exit 0
 
 # loopback is always handled the same way
-[ "$1" = "lo" ] && {
-    /sbin/ip link set lo up
-    /sbin/ip addr add 127.0.0.1/8 dev lo
+[ "$netif" = "lo" ] && {
+    ip link set lo up
+    ip addr add 127.0.0.1/8 dev lo
+    >/net.$netif.up
     exit 0
 }
 
+# XXX need error handling like dhclient-script
+
+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 /hostname.set ] || {
+	[ -n "$hostname" ] && mknod /hostname.set p 2>/dev/null &&
+	    hostname $hostname
+    }
+    [ -n "$srv" ] &&
+	echo "new_dhcp_server_identifier=$srv" > /net.$netif.dhcpopts
+
+    >/net.$netif.up
+    echo online > /sys/class/net/$netif/uevent
+}
+
+do_dhcp() {
+    reqs=subnet-mask,broadcast-address,routers,domain-name
+    reqs=${reqs},domain-name-servers,domain-search
+    reqs=${reqs},host-name,root-path,interface-mtu
+
+    for i in ip srv gw mask hostname; do
+	eval '[ "$'$i'" ] && echo '$i'="$'$i'"'
+    done > /net.$netif.override
+    [ -n "$ip" ] && echo bcast= >> /net.$netif.override
+
+    # /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 -R ${reqs} -pf /dhclient.$netif.pid $netif
+}
+
+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=off ;;
+    1)	autoconf=$1 ;;
+    2)	dev=$1; autoconf=$2 ;;
+    *)	ip=$1; srv=$2; gw=$3; mask=$4; hostname=$5; dev=$6; autoconf=$7
+	case $autoconf in
+	    ''|none|off) [ -n "$ip" ] && autoconf=static ;;
+	esac
+    esac
+    [ -n "$dev" ] || dev=$netif
+    [ -n "$autoconf" ] || autoconf=off
+}
+
 # spin through the kernel command line, looking for ip= lines
 for p in $(cat /proc/cmdline); do
-    [ "${p%%=*}" = "ip" ] || continue
-    ip=${p#ip=}
-    case $ip in
-	none|off) exit 0;; # we were told to not configure anything
-	dhcp|on|any) >/net.$1.dhcp; exit 0;; 
-	bootp|rarp|both) exit 0;; #dunno how to do this
-	*) echo ${ip} | \
-	    (IFS=':' read client server gw netmask hostname device autoconf
-		if [ -z "$device" -o "$device" = "$1"  ]; then
-		    case $autoconf in
-			dhcp|on|any) >/net.$1.dhcp ;;
-			none|off|'') # do some basic configuration
-			    /sbin/ip link set $1 up
-			    /sbin/ip addr add $client/$netmask dev $1
-			    [ "$gw" ] && /sbin/ip route add default via $gw dev $1
-			    >/net.$1.up ;;
-		    esac
-		fi
-		) ;;
-	*) continue;;
+    [ -n "${p%ip=*}" ] && continue
+    ip_to_var ${p#ip=}
+
+    # If this option isn't directed at our interface, skip it
+    [ "$dev" = "$netif" ] || continue
+
+    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
+exit 0
diff --git a/modules.d/40network/install b/modules.d/40network/install
index c0c13fc..7a13348 100755
--- a/modules.d/40network/install
+++ b/modules.d/40network/install
@@ -1,10 +1,9 @@
 #!/bin/bash
-dracut_install ip dhclient grep
+dracut_install ip dhclient hostname
 instmods ${modules:-=net}
 inst "$moddir/ifup" "/sbin/ifup"
 inst "$moddir/dhclient-script" "/sbin/dhclient-script"
 instmods =networking ecb arc4
 inst_rules "$moddir/60-net.rules"
 inst_hook pre-pivot 10 "$moddir/kill-dhclient.sh"
-inst_hook pre-mount 70 "$moddir/run-dhclient.sh"
 mkdir -p "${initdir}/var/run"
diff --git a/modules.d/40network/kill-dhclient.sh b/modules.d/40network/kill-dhclient.sh
index 70deda6..d1d15f4 100755
--- a/modules.d/40network/kill-dhclient.sh
+++ b/modules.d/40network/kill-dhclient.sh
@@ -1,4 +1,5 @@
 #!/bin/sh
 
-pid=$(pidof dhclient)
-[ -n "$pid" ] && kill $pid
+for f in /dhclient.*.pid; do
+    [ "$f" != "/dhclient.*.pid" ] && kill $(cat $f)
+done
diff --git a/modules.d/40network/run-dhclient.sh b/modules.d/40network/run-dhclient.sh
deleted file mode 100755
index bc32883..0000000
--- a/modules.d/40network/run-dhclient.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-for i in /net.*.dhcp; do
-    [ "$i" = '/net.*.dhcp' ] && break
-    dev=${i#/net.}; dev=${dev%.dhcp}
-    [ -f "/net.$dev.up" ] && continue
-    dhclient  -R 'subnet-mask,broadcast-address,time-offset,routers,domain-name,domain-name-servers,host-name,nis-domain,nis-servers,ntp-servers,root-path' -1 -q $dev &
-done
-wait
-    
-- 
1.6.0.6

--
To unsubscribe from this list: send the line "unsubscribe initramfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux