#!/bin/sh -e
### BEGIN INIT INFO
# Provides:          networking ifupdown
# Required-Start:    mountkernfs $local_fs urandom
# Required-Stop:     $local_fs
# Default-Start:     S
# Default-Stop:      0 6
# Short-Description: Raise network interfaces.
# Description:       Prepare /run/network directory, ifstate file and raise network interfaces, or take them down.
### END INIT INFO

setvar PATH = ""/sbin:/bin""
setvar RUN_DIR = ""/run/network""
setvar IFSTATE = ""$RUN_DIR/ifstate""
setvar STATEDIR = ""$RUN_DIR/state""

test -x /sbin/ifup || exit 0
test -x /sbin/ifdown || exit 0

source /lib/lsb/init-functions

setvar CONFIGURE_INTERFACES = 'yes'
setvar EXCLUDE_INTERFACES = ''
setvar VERBOSE = 'no'

test -f /etc/default/networking && source /etc/default/networking

setvar verbose = """"
test $VERBOSE = yes && setvar verbose = '-v'

proc process_exclusions {
    set -- $EXCLUDE_INTERFACES
    setvar exclusions = ""for d in @ARGV {
	setvar exclusions = ""-X $d $exclusions""
    }
    echo $exclusions
}

proc process_options {
    test -e /etc/network/options || return 0
    log_warning_msg "/etc/network/options still exists and it will be IGNORED! Please use /etc/sysctl.conf instead."
}

proc check_ifstate {
    if test ! -d $RUN_DIR  {
	if ! mkdir -p $RUN_DIR  {
	    log_failure_msg "can't create $RUN_DIR"
	    exit 1
	}
	if ! chown root:netdev $RUN_DIR  {
	    log_warning_msg "can't chown $RUN_DIR"
	}
    }
    if test ! -r $IFSTATE  {
	if ! :> "$IFSTATE"  {
	    log_failure_msg "can't initialise $IFSTATE"
	    exit 1
	}
    }
}

proc check_network_file_systems {
    test -e /proc/mounts || return 0

    if test -e /etc/iscsi/iscsi.initramfs {
	log_warning_msg "not deconfiguring network interfaces: iSCSI root is mounted."
	exit 0
    }

    while read DEV MTPT FSTYPE REST {
	case (DEV) {
	/dev/nbd*|/dev/nd[a-z]*|/dev/etherd/e*|curlftpfs* {
	    log_warning_msg "not deconfiguring network interfaces: network devices still mounted."
	    exit 0
	    }
	}
	case (FSTYPE) {
	nfs|nfs4|smbfs|ncp|ncpfs|cifs|coda|ocfs2|gfs|pvfs|pvfs2|fuse.httpfs|fuse.curlftpfs {
	    log_warning_msg "not deconfiguring network interfaces: network file systems still mounted."
	    exit 0
	    }
	}
    } < /proc/mounts
}

proc check_network_swap {
    test -e /proc/swaps || return 0

    while read DEV MTPT FSTYPE REST {
	case (DEV) {
	/dev/nbd*|/dev/nd[a-z]*|/dev/etherd/e* {
	    log_warning_msg "not deconfiguring network interfaces: network swap still mounted."
	    exit 0
	    }
	}
    } < /proc/swaps
}

proc ifup_hotplug {
    if test -d /sys/class/net
    {
	    setvar ifaces = $(for iface in $(ifquery --list --allow=hotplug)
			    do
				    link=${iface##:*}
				    link=${link##.*}
				    if [ -e "/sys/class/net/$link" ]
				    then
					# link detection does not work unless we up the link
					ip link set "$iface" up || true
					if [ "$(cat /sys/class/net/$link/operstate)" = up ]
					then
					    echo "$iface"
					fi
				    fi
			    done)
	    if test -n $ifaces
	    {
		ifup $ifaces @ARGV || true
	    }
    }
}

case (1) {
start {
	if init_is_upstart {
		exit 1
	}
	process_options
	check_ifstate

	if test $CONFIGURE_INTERFACES = no
	{
	    log_action_msg "Not configuring network interfaces, see /etc/default/networking"
	    exit 0
	}
	set -f
	setvar exclusions = $(process_exclusions)
	log_action_begin_msg "Configuring network interfaces"
	if test -x /sbin/udevadm {
		if test -n $(ifquery --list --exclude=lo) || test -n $(ifquery --list --allow=hotplug) {
			udevadm settle || true
		}
	}
	if ifup -a $exclusions $verbose && ifup_hotplug $exclusions $verbose
	{
	    log_action_end_msg $?
	} else {
	    log_action_end_msg $?
	}
	}

stop {
	if init_is_upstart {
		exit 0
	}
	check_network_file_systems
	check_network_swap

	log_action_begin_msg "Deconfiguring network interfaces"
	if ifdown -a --exclude=lo $verbose {
	    log_action_end_msg $?
	} else {
	    log_action_end_msg $?
	}
	}

reload {
	if init_is_upstart {
		exit 1
	}
	process_options

	log_action_begin_msg "Reloading network interfaces configuration"
	setvar state = $(ifquery --state)
	ifdown -a --exclude=lo $verbose || true
	if ifup --exclude=lo $state $verbose  {
	    log_action_end_msg $?
	} else {
	    log_action_end_msg $?
	}
	}

force-reload|restart {
	if init_is_upstart {
		exit 1
	}
	process_options

	log_warning_msg "Running $0 $1 is deprecated because it may not re-enable some interfaces"
	log_action_begin_msg "Reconfiguring network interfaces"
	ifdown -a --exclude=lo $verbose || true
	set -f
	setvar exclusions = $(process_exclusions)
	if ifup -a --exclude=lo $exclusions $verbose && ifup_hotplug $exclusions $verbose
	{
	    log_action_end_msg $?
	} else {
	    log_action_end_msg $?
	}
	}

* {
	echo "Usage: /etc/init.d/networking {start|stop|reload|restart|force-reload}"
	exit 1
	}
}

exit 0

# vim: noet ts=8