#!/bin/sh
#
# chkconfig: 2345 80 20
# description: Start and stop ISDN services
#
# Thomas Woerner <thomas.woerner@redhat.de>
# Ngo Than <than@redhat.de>

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

# Source configuration
. /etc/sysconfig/network

[ -s /etc/sysconfig/activeisdn ] || exit 0

function addprovider() {
    # clear environment
    PROVIDER=; USER=; PASSWORD=; ENCAP=; DIALMODE=; SECURE=; MSN=; PHONE_IN=
    PREFIX=; AREACODE=; PHONE_OUT=; CITY=; BUNDLING=; LOCAL_IP=; REMOTE_IP=
    NETWORK=; BROADCAST=; HUPTIMEOUT=; DNS=; HOSTNAME=; DOMAIN=; L2_PROT=
    L3_PROT=; CALLBACK=; CHARGEHUP=; CHARGEINT=; CBHUP=; CBDELAY=; DIALMAX=
    AUTH=; IHUP=; IP_FORWARD=; SLAVE_DELAY=; SLAVE_TRIGGER=
    SLAVE_DIALMODE=; SLAVE_MSN=; SLAVE_PHONE_IN=; SLAVE_PHONE_OUT=
    SLAVE_HUPTIMEOUT=; SLAVE_CALLBACK=; SLAVE_CHARGEHUP=; SLAVE_CHARGEINT=
    SLAVE_CBHUP=; SLAVE_CBDELAY=; SLAVE_DIALMAX=; SLAVE_IHUP=; DELDEFAULTROUTE=


    # load provider config
    source /etc/sysconfig/provider/conf-$1

    options=

    # Do some checks
    if [ -z "$MSN" ]; then
	echo "Error: $1: MSN not set"
	return
    fi
    if [ -z "$PHONE_OUT" ]; then
	echo "Error: $1: no outgoing phone number set"
	return
    fi
    if [ -z "$ENCAP" ]; then
	echo "Error: $1: Encapsulation not set"
	return
    fi
    if [ -z "$DIALMODE" ]; then
	echo "Error: $1: Dialmode not set"
	return
    fi
    if [ -z "$AUTH" ]; then
	AUTH="+pap -chap"
    fi
    # Check for channel bundling
    if [ "$BUNDLING" = "yes" ]; then
	if [ "$ENCAP" = "syncppp" ]; then
	    if [ -z "$SLAVE_MSN" ]; then
		SLAVE_MSN=$MSN;
	    fi
	    if [ -z "$SLAVE_PHONE_OUT" ]; then
		SLAVE_PHONE_OUT=$PHONE_OUT
	    fi
	    if [ -z "$SLAVE_PHONE_IN" ]; then
		SLAVE_PHONE_IN=$PHONE_IN
	    fi
	    if [ -z "$SLAVE_HUPTIMEOUT" ]; then
		SLAVE_HUPTIMEOUT=$HUPTIMEOUT
	    fi
	    if [ -z "$SLAVE_CHARGEHUP" ]; then
		SLAVE_CHARGEHUP=$CHARGEHUP
	    fi
	    if [ -z "$SLAVE_CHARGEINT" ]; then
		SLAVE_CHARGEINT=$CHARGEINT
	    fi
	    if [ -z "$SLAVE_DBHUP" ]; then
		SLAVE_DBHUP=$DBHUP
	    fi
	    if [ -z "$SLAVE_IHUP" ]; then
		SLAVE_IHUP=$IHUP
	    fi
	    if [ -z "$SLAVE_DIALMAX" ]; then
		SLAVE_DIALMAX=$DIALMAX
	    fi
	    if [ -z "$SLAVE_CALLBACK" ]; then
		SLAVE_CALLBACK=$CALLBACK
	    fi
	    if [ -z "$SLAVE_CBDELAY" ]; then
		SLAVE_CBDELAY=$CBDELAY
	    fi

	    # slave dialmode auto:
	    # slave_delay and slave_trigger hast to be set
	    if [ "$SLAVE_DIALMODE" = "auto" ]; then
		if [ -z "$SLAVE_DELAY" ]; then
		    echo " Error: Slave delay not set - slave interface disabled";
		    BUNDLING=
		fi
		if [ -z "$SLAVE_TRIGGER" ]; then
		    echo " Error: Slave triggering not set - slave interface disabled";
		    BUNDLING=
		fi
	    fi
	else
	    echo " Error: $1 channel bundling only supported with syncppp - slave interface disabled"
	    BUNDLING=
	fi
    fi

    # some settings
    if [ -z "$L2_PROT" ]; then
	L2_PROT="hdlc"
    fi
    if [ -z "$L3_PROT" ]; then
	L3_PROT="trans"
    fi

    # checks for syncppp
    if [ "$ENCAP" = "syncppp" ]; then
	device=ippp$sync_devices
        sync_devices=$[$sync_devices+1]

	# 1=delete default route, if exists
	if [ "$DELDEFAULTROUTE" = "enabled" -o -z "$DELDEFAULTROUTE" ] ; then
	    options="$options deldefaultroute"
	fi
	
	# we use authentication with pap and/or chap
	# 
	_auth=`echo "$AUTH" | sed 's/[a-z -]*//g'`
	if [ -n "$_auth" ]; then
	    if [ -z "$USER" ]; then
		echo " Error: $1 (syncppp) user is not set"
		return
	    fi

	    options="$options user $USER"
	    
	    # authentication options:
	    # +pap and/or +chap does not work with ipppd correctly - removing
	    # them
	    AUTH=`echo "$AUTH" | sed 's/+[a-z]*//g'`;
	fi
    fi

    # checks for rawip
    if [ "$ENCAP" = "rawip" ]; then
	device=isdn$raw_devices
        raw_devices=$[$raw_devices+1]
	if [ -z "$LOCAL_IP" -o -z "$REMOTE_IP" ]; then
	    echo " Error: $1 (rawip) local or remote ip not set"
	    return
        fi
    fi

    # did we got a device
    if [ -z "$device" ]; then
	echo " Error: $1: cannot determine device"
	return
    fi

    echo " adding provider '$1' on device '$device'"

    isdnctrl addif $device
    isdnctrl eaz $device $MSN
    for i in $PHONE_OUT; do
        isdnctrl addphone $device out $AREACODE$i
    done
    for i in $PHONE_IN; do
        isdnctrl addphone $device in $i
    done
    isdnctrl l2_prot $device $L2_PROT
    isdnctrl l3_prot $device $L3_PROT
    isdnctrl encap $device $ENCAP
    isdnctrl dialmode $device $DIALMODE
    if [ -n "$SECURE" ]; then
	isdnctrl secure $device $SECURE
    fi
    if [ -n "$HUPTIMEOUT" ]; then
	isdnctrl huptimeout $device $HUPTIMEOUT
    fi
    if [ -n "$CHARGEHUP" ]; then
	isdnctrl chargehup $device $CHARGEHUP
    fi
    if [ -n "$CHARGEINT" ]; then
	isdnctrl chargeint $device $CHARGEINT
    fi
    if [ -n "$DBHUP" ]; then
	isdnctrl cbhup $device $CBHUP
    fi
    if [ -n "$IHUP" ]; then
	isdnctrl ihup $device $IHUP
    fi
    if [ -n "$DIALMAX" ]; then
	isdnctrl dialmax $device $DIALMAX
    fi
    if [ -n "$CALLBACK" ]; then
	isdnctrl callback $device $CALLBACK
    else
	isdnctrl callback $device off
    fi
    if [ -n "$CBDELAY" ]; then
	isdnctrl cbdelay $device $CBDELAY
    fi

    if [ "$ENCAP" = "syncppp" ]; then
	# set config options for /etc/sysconfig/network-scripts/ifcfg-$device
	ifcfg_file="/etc/sysconfig/network-scripts/ifcfg-$device"
	echo "DEVICE=$device" > $ifcfg_file
	options="$options ipparam $device"
	dyn_local=
	isdnctrl pppbind $device
	if [ -z "$LOCAL_IP" ]; then
	    dyn_local=1
	    LOCAL_IP="0.0.0.0"
	    options="$options ipcp-accept-local"
	else
	    options="$options noipdefault"
	fi

	if [ -z "$REMOTE_IP" ]; then
	    options="$options ipcp-accept-remote"

	    # Activate network interface
	    ifconfig $device $LOCAL_IP up
	else
	    # Activate network interface
	    ifconfig $device $LOCAL_IP pointopoint $REMOTE_IP up
	fi

	# do we have all dynamically?
	if [ -n "dyn_local" -a -z "$REMOTE_IP" ]; then
       	    # Set the local and/or remote interface IP addresses
	    options="$LOCAL_IP:0.0.0.0 $options"
	fi

	# Add default route while connection
	options="$options defaultroute"

	# Disable Van Jacobson style TCP/IP header compression and
        # VJ connection-ID compression
	options="$options -vj -vjccomp"

	# Disable Address/Control compression, protocol field compression and
	# BSD-Compression scheme
	options="$options -ac -pc -bsdcomp"

#	# Set max receive and max transmit units
#	options="$options mru 1524 mtu 1500"
#
#	# set host name
#	if [ -n "$HOSTNAME" ]; then
#	    options="$options hostname $HOSTNAME"
#	fi
#
	# set domain name
	if [ -n "$DOMAIN" ]; then
	    options="$options domain $DOMAIN"
	    echo "DOMAIN=$DOMAIN" >> $ifcfg_file
	fi

	# Set authentication options
	for i in $AUTH; do
	    options="$options $i"
	done

	# check dns entry
	if [ -z "$DNS" ]; then
	    options="$options ms-get-dns"
	    if [ "$RESOLV_MODS" != "no" ]; then
		echo "RESOLV_MODS=\"yes\"" >> $ifcfg_file
	    fi
	else
	    for i in $DNS; do
		options="$options ms-dns $i"
		echo "DNS1=$DNS" >> $ifcfg_file
	    done
	fi

	# Add device
	options="$options /dev/$device"

	# Create slave device if bundling enabled
	if [ "$BUNDLING" = "yes" ]; then
	    slave=ippp$sync_devices
	    sync_devices=$[$sync_devices+1]

	    options="$options /dev/$slave +mp"

	    # Create slave and set options
	    isdnctrl addslave $device $slave
	    isdnctrl eaz $device $SLAVE_MSN
	    for i in $SLAVE_PHONE_OUT; do
	        isdnctrl addphone $slave out $AREACODE$i
	    done
	    for i in $SLAVE_PHONE_IN; do
	        isdnctrl addphone $slave in $i
	    done
	    isdnctrl l2_prot $device $L2_PROT
	    isdnctrl l3_prot $device $L3_PROT
	    isdnctrl encap $device $ENCAP
	    isdnctrl dialmode $device $SLAVE_DIALMODE
	    if [ -n "$SECURE" ]; then
	        isdnctrl secure $device $SECURE
	    fi
	    if [ -n "$SLAVE_HUPTIMEOUT" ]; then
	        isdnctrl huptimeout $device $SLAVE_HUPTIMEOUT
	    fi
	    if [ -n "$SLAVE_CHARGEHUP" ]; then
	        isdnctrl chargehup $device $SLAVE_CHARGEHUP
	    fi
	    if [ -n "$SLAVE_CHARGEINT" ]; then
	        isdnctrl chargeint $device $SLAVE_CHARGEINT
	    fi
	    if [ -n "$SLAVE_DBHUP" ]; then
	        isdnctrl cbhup $device $SLAVE_CBHUP
	    fi
	    if [ -n "$SLAVE_IHUP" ]; then
	        isdnctrl ihup $device $SLAVE_IHUP
	    fi
	    if [ -n "$SLAVE_DIALMAX" ]; then
	        isdnctrl dialmax $device $SLAVE_DIALMAX
	    fi
	    if [ -n "$SLAVE_CALLBACK" ]; then
	        isdnctrl callback $device $SLAVE_CALLBACK
	    else
	        isdnctrl callback $device off
	    fi
	    if [ -n "$SLAVE_CBDELAY" ]; then
		isdnctrl cbdelay $device $SLAVE_CBDELAY
	    fi

	    # Options for master device
	    if [ -n "$SLAVE_DELAY" ]; then
		isdnctrl sdelay $device $SLAVE_DELAY
	    fi
	    if [ -n "SLAVE_TRIGGER" ]; then
		isdnctrl trigger $device $SLAVE_TRIGGER
	    fi
	fi

	# Use provider options file instead
	if [ -f "/etc/ppp/options-$1" ]; then
	    options="file /etc/ppp/options-$1"
	fi

	# Start ipppd
	ipppd $options

	if [ -n "$dyn_local" ]; then
	    echo "1" > /proc/sys/net/ipv4/ip_dynaddr
	fi
    fi

    if [ "$ENCAP" = "rawip" ]; then
	ifconfig $device $LOCAL_IP pointopoint $REMOTE_IP up
	route add default gw $REMOTE_IP
    fi

    if [ "$IP_FORWARD" = "1" ]; then
	echo 1 > /proc/sys/net/ipv4/ip_forward
    fi

    echo "$device $1" >> /var/run/isdn
    touch /var/lock/subsys/isdn
}
function removeprovider() {
    echo " removing provider '$1' on device '$2'"
    ifconfig $2 down
    isdnctrl delif $2
}

sync_devices=0
raw_devices=0

case "$1" in
    start)
	echo "Starting ISDN: "

	if [ -f /etc/sysconfig/isdncard ]; then
	    source /etc/sysconfig/isdncard
	fi

	if [ -z "$MODULE" -o -z "$RESOURCES" ]; then
	    echo "no isdn card defined"
	    exit 1
	fi

	# load modules
	echo " loading modules"
	modprobe $MODULE $RESOURCES

	#start logging
	if [ "$MODULE" = "hisax" ]; then
	    hisaxctrl HiSax 1 0x3ff
	fi
	daemon isdnlog /dev/isdnctrl0 -m496 -x0x3fff -M -w2 -S -s -O+/var/log/isdnctrl &

	tail -80f /var/log/isdnctrl > /dev/tty11 &

	# start provider configurations
	for prov in `cat /etc/sysconfig/activeisdn`; do
	    if [ -f "/etc/sysconfig/provider/conf-$prov" ]; then
		# execute function in sub-shell to have clear environment
		addprovider $prov
	    else
		echo "Error: cannot find file '/etc/sysconfig/provider/conf-$prov'!";
	    fi
	done

	echo
	;;
    stop)
	echo "Stopping ISDN: "
	
	if [ ! -f /var/run/isdn ]; then
	    echo " ISDN not running?"
	    exit 0
	fi

	# kill ipppd if running
	killproc ipppd

	while read device provider; do
	    removeprovider $provider $device
	    rm -f /etc/sysconfig/network-scripts/ifcfg-$device
        done < /var/run/isdn
	rm -f /var/run/isdn
	rm -f /var/lock/subsys/isdn

	# stop logging
	killproc isdnlog

	PID=`ps auxww | grep tail | grep isdnctrl | awk '{print $2}'`
	if [ -n "$PID" ]; then
	    kill $PID
	fi

	if [ -f /etc/sysconfig/isdncard ]; then
	    source /etc/sysconfig/isdncard
	fi

	if [ -z "$MODULE" -o -z "$RESOURCES" ]; then
	    echo "no isdn card defined"
	    exit 1
	fi

	# Unload hisax modules
	echo " Unloading modules"
	modprobe -r $MODULE

	echo
	;;
    restart)
	$0 stop
	$0 start
	;;
    *)
	echo "Usage: isdn {start|stop|restart}"
	exit 1
esac

exit 0
