#!/bin/sh

WITHOUT_RC_COMPAT=1

# Source function library.
. /etc/init.d/functions

cd /etc/sysconfig/network-scripts
. network-functions

# we need it here because DHCP configuration relies on it
SourceIfNotEmpty /etc/sysconfig/network

need_hostname

CONFIG=${1}

[ -z "$CONFIG" ] && {
    msg_usage "ifup <device name>"
    exit 1
}

[ -f "$CONFIG" ] || CONFIG="ifcfg-$CONFIG"
[ -f "$CONFIG" ] || {
    msg_usage "ifup <device name>"
    exit 1
}

if [ "$UID" != 0 ]; then
	USERNETCTL=/usr/sbin/usernetctl
	if [ -x "$USERNETCTL" ]; then
		if "$USERNETCTL" "$CONFIG" report; then
			exec "$USERNETCTL" "$CONFIG" up
		fi
	fi
	echo "Users cannot control this device." >&2
	exit 1
fi

source_config
if [ "$IN_HOTPLUG" = "1" ]; then
	is_yes $USE_HOTPLUG || exit 0
fi

if [ "$2" = boot ] && ! is_yes "$ONBOOT"; then
	exit 0
fi

IPSETUP=no

DEVICETYPE=`echo "$DEVICE" | sed "s/[0-9]*$//"`
REALDEVICE=`echo "$DEVICE" | sed 's/[.:].*//g'`
if echo "$DEVICE" | fgrep -qs ':'; then
    ISALIAS=yes
else
    ISALIAS=no
fi

SBIN_IWCONFIG=/sbin/iwconfig
SBIN_IWSPY=/sbin/iwspy
SBIN_IWPRIV=/sbin/iwpriv

if [ -n "$WIRELESS_ENC_KEY" -a -x "$SBIN_IWCONFIG" ]; then
	"$SBIN_IWCONFIG" ${DEVICE} enc "$WIRELESS_ENC_KEY" >/dev/null 2>&1
fi

IFS=, read BOOTPROTO BOOTPROTO_FALLBACK <<< "$BOOTPROTO"

if [ "$BOOTPROTO" = dhcp ]; then
    DYNCONFIG=true
fi

# Old BOOTP variable
if is_yes "$BOOTP"; then
    BOOTPROTO=bootp
fi

if [ "$BOOTPROTO" = bootp ]; then
    DYNCONFIG=true
    DHCP_CLIENT=/sbin/pump
fi

ExecIfExecutable /usr/local/sbin/ifup-pre-local "$DEVICE"

OTHERSCRIPT="/etc/sysconfig/network-scripts/ifup-$DEVICETYPE"

if [ -x "$OTHERSCRIPT" ]; then
    exec "$OTHERSCRIPT" "$CONFIG" "$2"
fi

# VLAN configuration
BIN_VCONFIG=/usr/bin/vconfig
SourceIfNotEmpty /etc/sysconfig/vlan

if [ -n "$VLAN_TRUNK_IF" -a -x "$BIN_VCONFIG" ]; then
    vlan_flags=
    if [ -n "$ENABLE_VLAN_DHCP" ]; then
        vlan_flags="1 1"
    fi

    # VLAN name types:
    #	VLAN_PLUS_VID 		= vlan0005
    #	VLAN_PLUS_VID_NO_PAD	= vlan5
    #	DEV_PLUS_VID		= eth0.0005
    #	DEV_PLUS_VID_NO_PAD	= eth0.5
    case "$VLAN_NAMING" in
	VLAN_PLUS_VID|VLAN_PLUS_VID_NO_PAD)
	    vlan_id=`echo $DEVICE | sed "s/^vlan0*//g"`
	    ;;
	DEV_PLUS_VID|DEV_PLUS_VID_NO_PAD)
	    vlan_id=`echo $DEVICE | sed "s/^[a-z0-9]*\.0*//g"`
	    ;;
    esac

    if [ -n "$vlan_id" ]; then
	"$BIN_VCONFIG" add "$VLAN_TRUNK_IF" "$vlan_id" >/dev/null 2>&1

	if [ -n "$vlan_flags" ]; then
	    "$SBIN_VCONFIG" set_flag "$DEVICE" "$vlan_flags" >/dev/null 2>&1
	fi
    fi
fi 

# is this device available? (this catches PCMCIA devices for us)
LC_ALL= LANG= /sbin/ifconfig "$REALDEVICE" 2>&1 |fgrep -qs 'not found'
if [ "$?" = 0 ]; then
    echo "Delaying $DEVICE initialization."
    exit 1
fi

IFENSLAVE=/sbin/ifenslave
if is_yes "$SLAVE" && is_no "$ISALIAS" && [ -n "$MASTER" -a -x "$IFENSLAVE" ]; then
	RFLAG=
	is_yes "$RECEIVEONLY" && RFLAG="-r"

	ip link set $DEVICE down
	ip link set $MASTER up
	# Check, if master needs additional configuration. It is required
	# if it should be configured via DHCP but has no slaves yet.
	if fakeMAC "$MASTER" && ! ip address show dev $MASTER | grep -q '^ *inet'
	then
		masterconf=yes
	fi
	echo "Enslaving $DEVICE to $MASTER"
	"$IFENSLAVE" $RFLAG "$MASTER" "$DEVICE"

	# If additional configuration of master is required,
	# continue with master configuration, assuming
	# configuration protocol dhcp, else exit
	if [ -n "$masterconf" ]; then
		DEVICE=$MASTER
		DYNCONFIG=true
	else
		exit 0
	fi
fi

# Now, run the specific script for Wireless LAN interfaces
# Note : we need the wireless parameters to be set up before IP parameters,
# so that we can perform DHCP over the Wireless link if needed. Jean II

if [ -n "$WIRELESS_MODE$WIRELESS_ESSID$WIRELESS_NWID$WIRELESS_FREQ$WIRELESS_SENS$WIRELESS_RATE$WIRELESS_KEY$WIRELESS_RTS$WIRELESS_FRAG$WIRELESS_IWCONFIG$WIRELESS_IWSPY$WIRELESS_IWPRIV$WIRELESS_ESSID" -a -x "$SBIN_IWCONFIG" ] ; then
	# Set all desired settings via iwconfig

	# Mode need to be first : some settings apply only in a specific mode !
	if [ "$WIRELESS_MODE" ] ; then
		"$SBIN_IWCONFIG" $DEVICE mode $WIRELESS_MODE
	fi
	# This is a bit hackish, but should do the job right...
	if [ "$WIRELESS_ESSID" ] || [ "$WIRELESS_MODE" ] ; then
		NICKNAME=`/bin/hostname`
		"$SBIN_IWCONFIG" $DEVICE nick $NICKNAME >/dev/null 2>&1
	fi
	# Regular stuff...
	if [ "$WIRELESS_NWID" ] ; then
		"$SBIN_IWCONFIG" $DEVICE nwid $WIRELESS_NWID
	fi
	if [ "$WIRELESS_FREQ" ] ; then
		"$SBIN_IWCONFIG" $DEVICE freq $WIRELESS_FREQ
	elif [ "$WIRELESS_CHANNEL" ] ; then
		"$SBIN_IWCONFIG" $DEVICE channel $WIRELESS_CHANNEL
	fi
	if [ "$WIRELESS_SENS" ] ; then
		"$SBIN_IWCONFIG" $DEVICE sens $WIRELESS_SENS
	fi
	if [ "$WIRELESS_RATE" ] ; then
		"$SBIN_IWCONFIG" $DEVICE rate $WIRELESS_RATE
	fi
	if [ "$WIRELESS_KEY" ] ; then
		"$SBIN_IWCONFIG" $DEVICE key $WIRELESS_KEY
	fi
	if [ "$WIRELESS_RTS" ] ; then
		"$SBIN_IWCONFIG" $DEVICE rts $WIRELESS_RTS
	fi
	if [ "$WIRELESS_FRAG" ] ; then
		"$SBIN_IWCONFIG" $DEVICE frag $WIRELESS_FRAG
	fi
	# More specific parameters
	if [ "$WIRELESS_IWCONFIG" ] ; then
		"$SBIN_IWCONFIG" $DEVICE $WIRELESS_IWCONFIG
	fi
	if [ "$WIRELESS_IWSPY" ] ; then
		"$SBIN_IWSPY" $DEVICE $WIRELESS_IWSPY
	fi
	if [ "$WIRELESS_IWPRIV" ] ; then
		"$SBIN_IWPRIV" $DEVICE $WIRELESS_IWPRIV
	fi
	# ESSID need to be last : most device re-perform the scanning/discovery
	# when this is set, and things like encryption keys are better be
	# defined if we want to discover the right set of APs/nodes.
	if [ "$WIRELESS_ESSID" ] ; then
		"$SBIN_IWCONFIG" $DEVICE essid "$WIRELESS_ESSID"
	fi
fi

# set interface-specific parameters
[ -n "$MACADDR" ] && ip link set dev "$DEVICE" address "$MACADDR"
[ -n "$MTU" ] &&     ip link set dev "$DEVICE" mtu $MTU
ip link set dev "$DEVICE" $(ip_link_flag arp $ARP) $(ip_link_flag promisc $PROMISC) \
$(ip_link_flag allmulti $ALLMULTI) $(ip_link_flag multicast $MULTICAST)


if [ -n "$DYNCONFIG" -a -z "$DHCP_CLIENT" ]; then
	if [ -x /sbin/dhcpcd ]; then
		DHCP_CLIENT=/sbin/dhcpcd
	elif [ -x /sbin/pump ]; then
		DHCP_CLIENT=/sbin/pump
	elif [ -x /sbin/dhcpxd ]; then
		DHCP_CLIENT=/sbin/dhcpxd
	elif [ -x /sbin/dhclient ]; then
		DHCP_CLIENT=/sbin/dhclient
	else 
		echo "Can't find a dhcp client"
		exit 1;
	fi
fi  

DHCP_ARGS=
if [ -n "$DHCP_CLIENT" ]; then
case "${DHCP_CLIENT##*/}" in
	dhcpcd)
		[ -z "$BOOTPROTO_FALLBACK" ] || DHCP_ARGS="-t 30"
		[ -z "$DHCP_HOSTNAME" ] || DHCP_ARGS="$DHCP_ARGS -h $DHCP_HOSTNAME"
		[ -z "$NEEDHOSTNAME" ] || DHCP_ARGS="$DHCP_ARGS -H"
		is_yes "$PEERNTP" || DHCP_ARGS="$DHCP_ARGS -N"
		! is_no "$PEERDNS" || DHCP_ARGS="$DHCP_ARGS -R"
		DHCP_ARGS="$DHCP_ARGS $DEVICE"
		;;
	pump)
		[ -z "$DHCP_HOSTNAME" ] || DHCP_ARGS="-h $DHCP_HOSTNAME"
		[ -z "$NEEDHOSTNAME" ] || DHCP_ARGS="$DHCP_ARGS --lookup-hostname"
		! is_no "$PEERDNS" || DHCP_ARGS="$DHCP_ARGS -R"
		DHCP_ARGS="$DHCP_ARGS -i $DEVICE"
		;;
	dhcpxd)
		# Dhcpxd don't support NEED_HOSTNAME ? guess i need time to patch
		# this animal
		[ -n "$DHCP_HOSTNAME" ] && DHCP_ARGS="-H $HOSTNAME"
		DHCP_ARGS="$DHCP_ARGS -w $DEVICE"
		;;
	dhclient)
		# We should limit dhclient activity to first try
		# if we have fallback method
		[ -z "$BOOTPROTO_FALLBACK" ] || DHCP_ARGS="-1"
		# Can't specify a host with dhclient ? same remark for
		# $NEEDHOSTNAME this client suck !!!
		DHCP_ARGS="$DHCP_ARGS $DEVICE"
		;;
esac
fi

ZCIP=/sbin/zcip
ZCIP_ARGS="-s -i $DEVICE"

if [ -n "$DYNCONFIG" ]; then
	if is_yes "$CHECK_ETH_LINK"; then
		check_eth_link
		if [ "$?" = 1 ]; then
			echo -n "link is down, DHCP discovery is impossible"
			exit 1
		fi
	fi
	echo -n "Determining IP information for $DEVICE via ${DHCP_CLIENT##*/}..."
	if $DHCP_CLIENT $DHCP_ARGS; then
		echo " done."
	elif [ "$BOOTPROTO_FALLBACK" = zcip ]; then
		if [ ! -x $ZCIP ]; then
			echo "WARNING: try to install zcip package first!"
		else
			echo 
			echo -n "Determining IP information for $DEVICE via ${ZCIP##*/}..."
			if $ZCIP $ZCIP_ARGS; then
				echo " done."
			else
				echo " failed."
				exit 1
			fi
		fi
	else
		echo " failed."
		exit 1
	fi
elif [ "$BOOTPROTO" = zcip ]; then
	if is_yes "$CHECK_ETH_LINK"; then
		check_eth_link
		if [ "$?" = 1 ]; then
			echo -n "link is down, ZeroConf discovery is impossible"
			exit 1
		fi
	fi
	if [ ! -x $ZCIP ]; then
		echo "WARNING: try to install zcip package first!"
	else
		echo -n "Determining IP information for $DEVICE via ${ZCIP##*/}..."
		if $ZCIP $ZCIP_ARGS; then
			echo " done."
		else 
			echo " failed."
			exit 1
		fi
	fi
elif [ "$BOOTPROTO" = static ]; then
	if [ -z "$NETMASK" ]; then
		eval `/bin/ipcalc --netmask "$IPADDR"`
	fi

	if [ -z "$BROADCAST" ]; then
		eval `/bin/ipcalc --broadcast "$IPADDR" "$NETMASK"`
	fi

	if [ -z "$NETWORK" ]; then
		eval `/bin/ipcalc --network "$IPADDR" "$NETMASK"`
	fi
    
	ifconfig "$DEVICE" "$IPADDR" netmask "$NETMASK" broadcast "$BROADCAST"

	# don't re-add subnet route on 2.2 kernels, but add a route
	# to a non-local subnet.
	# stupid hack, but it should work
	if is_no "$ISALIAS" && [ -z "$(route -n |sed "s/ .*//" |fgrep "$NETWORK")" ]; then
		route add -net "$NETWORK" netmask "$NETMASK" dev "$DEVICE"
	fi

	# deal with default gateway

	if [ -z "$GATEWAYDEV" -o "$GATEWAYDEV" = "$DEVICE" ]; then
		# set up default gateway
		if [ -n "$GATEWAY" ]; then
#			route add default gw "$GATEWAY" "$DEVICE"
# $DEVICE is redundant here and had to be thrown away years ago
			ip route add default via "$GATEWAY"
			DEFGW="$GATEWAY"
		elif [ "$GATEWAYDEV" = "$DEVICE" ]; then
			ip route add default dev "$DEVICE"
		fi
	fi
else
# BOOTPROTO unset or 'none'
	ip link set dev "$DEVICE" up
fi

SYSCTL_PREFIX=net.ipv4.conf.$DEVICE
[ -n "$SYSCTL_FORWARDING" ] &&   sysctl -w $SYSCTL_PREFIX.forwarding=$SYSCTL_FORWARDING
[ -n "$SYSCTL_RP_FILTER" ] &&    sysctl -w $SYSCTL_PREFIX.rp_filter=$SYSCTL_RP_FILTER
[ -n "$SYSCTL_LOG_MARTIANS" ] && sysctl -w $SYSCTL_PREFIX.log_martians=$SYSCTL_LOG_MARTIANS

. /etc/sysconfig/network

if is_yes "$IPX"; then
	/etc/sysconfig/network-scripts/ifup-ipx "$DEVICE"
fi

exec /etc/sysconfig/network-scripts/ifup-post "$CONFIG" "$2"
