#!/bin/sh
# Configure	WAN Router Configuration Script.
#
# Copyright	(c) 1996, Sangoma Technologies Inc.
#
#		This program is free software; you can redistribute it and/or
#		modify it under the terms of the GNU General Public License
#		as published by the Free Software Foundation; either version
#		2 of the License, or (at your option) any later version.
# ----------------------------------------------------------------------------
# Oct 04, 1999  Nenad Corbic    Updated for v2.1.0
# Aug 04, 1999  Nenad Corbic    Update  for v2.0.5
# Oct 13, 1998	Jaspreet Singh	Updated for v2.0.4
# Aug 31, 1998	Jaspreet Singh	Updated for v2.0.3
# Dec 09, 1997	Jaspreet Singh	Updated for v2.0.2
# Nov 28, 1997  Jaspreet Singh  Updated for v2.0.1
# Nov 06, 1997	Jaspreet Singh	Updated for v2.0.0
# Oct 16, 1997	Jaspreet Singh	Checks for UID = 0
# Dec 31, 1996	Gene Kozin	Initial version based on Sangoma's WANPIPE(tm)
# ============================================================================

####### FUNCTION DEFINITIONS #################################################

# ----------------------------------------------------------------------------
# Clear screen.
# ----------------------------------------------------------------------------
clearscr()
{
	# check if the terminal environment is set up
	[ "$TERM" ] && clear 2> /dev/null
}

# ----------------------------------------------------------------------------
# Pause.
# ----------------------------------------------------------------------------
pause()
{
	[ $# -ne 0 ] && echo -e $* >&2
	echo -e "Press [Enter] to continue...\c" >&2
	read tmp
	return 0
}

# ----------------------------------------------------------------------------
# Display error message.
# ----------------------------------------------------------------------------
error()
{
	echo -e "Error: $*!" >&2
	return 0
}

# ----------------------------------------------------------------------------
# Prompt user for input.
# ----------------------------------------------------------------------------
prompt()
{
	echo -ne "$*" >&2
	read CMD rest
	return 0
}

# ----------------------------------------------------------------------------
# Get Yes/No answer.
# ----------------------------------------------------------------------------
getyn()
{
	while	prompt "$* (y/n) "
	do	case $CMD in
			[yY])	return 0
 				;;
			[nN])	return 1
				;;
			*)	echo -e "Please answer y or n" >&2
				;;
		esac
	done
}

# ----------------------------------------------------------------------------
# Select an item from the list.
# Return:	0 - selection is in $SEL
#		1 - quit or empty list
# ----------------------------------------------------------------------------
get_select()
{
	[ $# -eq 0 ] && return 1

	while prompt "Please enter your selection (1..$# or q) ->"
	do	case ${CMD:="0"} in
		[0-9]|[0-9][0-9])
			[ $CMD -lt 1 -o $CMD -gt $# ] && continue
			CMD=`expr $# - $CMD + 1 2>/dev/null`
			until [ $# -eq $CMD ]
			do	shift
			done
			SEL=$1
			return 0
			;;
		q|Q)	return 1
			;;
		esac
	done
}

# ----------------------------------------------------------------------------
# Select an item from the list.
# Return:	0 - selection is in $SEL
#		1 - quit or empty list
# ----------------------------------------------------------------------------
select_list()
{
	[ $# -eq 0 ] && return 1

	col=`expr $# / 10 + 1`
	cnt=0
	for option in $*
	do	cnt=`expr $cnt + 1`
		echo -en "\t$cnt) $option"
		[ `expr $cnt % $col` -eq 0 ] && echo ""
	done
	echo -e "\tq) quit\n"
	get_select $*
}

# ----------------------------------------------------------------------------
# Check to see if a value belongs to the list.
# Return:	0 - yes
#		1 - no
# ----------------------------------------------------------------------------
check_list()
{
	val=$1
	shift
	for i in $*; do [ "$val" = "$i" ] && return 0; done
	return 1
}

# ----------------------------------------------------------------------------
# Add WAN driver.
# ----------------------------------------------------------------------------
add_driver()
{
	banner
	cat << ENDOFTEXT
WAN dirvers are loadable kernel modules usually named something like foobar.o
and located in $MOD_DIR directory (or its subdirectories) together
with the router module and other kernel modules.  You can load them manually
using insmod or modprobe commands or you can add them to the /etc/modules file
to be loaded every time your system boots.

Alternatively, you can add WAN driver modules to the router's driver list and
they will be loaded automatically only when WAN router starts and unloaded
when you shut it down with 'router stop' command.  When entering driver name
you can omit trailing '.o' and path.
ENDOFTEXT
	pause ""
	get_drvlist
	DRV_LIST=$WAN_DRIVERS
	while	select_drvname
	do
		check_list $DRV_NAME $DRV_LIST && {
			echo -e "\nDriver named $DRV_NAME already selected!\n"
			pause
			continue
		}
		check_driver $DRV_NAME || continue
		DRV_LIST="$DRV_LIST $DRV_NAME"
	done

	[ "$WAN_DRIVERS" = "$DRV_LIST" ] && return 0

	# Update configuration filae and build module dependencies.
	banner
	echo "Building module dependencies. Please wait..."
	depmod -a 2> /dev/null

	echo "Updating configuration file..."
	cp $ROUTER_RC $TMPFILE
	echo /^WAN_DRIVERS=/s/=.*/=\"$DRV_LIST\"/ > $TMPFILE.2
	sed -f $TMPFILE.2 $TMPFILE > $ROUTER_RC
	return 0
}

# ----------------------------------------------------------------------------
# Get list of WAN drivers.
# ----------------------------------------------------------------------------
get_drvlist()
{
	WAN_DRIVERS=
	eval `grep "^WAN_DRIVERS=" $ROUTER_RC`
}

# ----------------------------------------------------------------------------
# Select driver name.
# ----------------------------------------------------------------------------
select_drvname()
{
	banner
	[ "$DRV_LIST" ] && {
		echo -e "Currently, the following drivers are selected:\n"
		for i in $DRV_LIST
		do echo -e "\t$i"
		done
	}
	prompt "\nEnter new driver name or hit [Enter] for the main menu: "
	[ "$CMD" ] && DRV_NAME=$CMD
}

# ----------------------------------------------------------------------------
# Check driver presence.
# ----------------------------------------------------------------------------
check_driver()
{
	tmp=`find $MOD_DIR -follow -name $1 -o -name $1.o`
	[ "$tmp" ] && return 0
	getyn "\nDriver not found! Add anyway"
}

# ----------------------------------------------------------------------------
# Delete Adapter.
# ----------------------------------------------------------------------------
del_driver()
{
	banner
	get_drvlist
	[ -z "$WAN_DRIVERS" ] && {
		echo "No drivers available!"
		pause ""
		return 0
	}

	echo -e "Select WAN driver to remove:\n"
	select_list $WAN_DRIVERS || return 0

	# Edit configuration file.
	cp $ROUTER_RC $TMPFILE
	sed  '/^WAN_DRIVERS=/s/ *'$SEL'//' $TMPFILE > $ROUTER_RC
	return 0
}

# ----------------------------------------------------------------------------
# Create interface configuration file.
# ----------------------------------------------------------------------------
add_interface()
{
	while
		IPADDR=
		NETMASK=
		POINTOPOINT=
		BROADCAST=
		NETWORK=
		GATEWAY=
		select_ifname
	do
		IF_CONF=$IFCONF_DIR/$IF_NAME
		[ -f $IF_CONF ] && {
			pause "\nConfiguration file $IF_CONF already exists!"
			continue
		}
		select_ipaddr || continue
		select_netmask
		select_pointopoint
		select_network

		banner
		echo -e "You have selected the following configuration:\n"
		show_ifconf $IF_NAME
		getyn "\nCreate configuration file" || continue

		# Create configuration file
		create_ifconf
		[ -f $IF_CONF ] || {
			echo "Hmm... Seems like an error. Continue" && continue
			return 1
		}
	done

	banner
	cat << ENDOFTEXT
Interface configuration files have been successfully created.  Don't forget to
update router configuration file $ROUTER_CONF.  You must add an entry to the
[interfaces] section of this file for each new interface and, optionally,
create a new section for the interface-specific configuration options.  Please
read WAN Router User's Manual and your WAN driver documentation for more
information.
ENDOFTEXT
	pause ""
	return 0
}

# ----------------------------------------------------------------------------
# Select interface name.
# ----------------------------------------------------------------------------
select_ifname()
{
	banner
	cat << ENDOFTEXT
Network interfaces are known to Linux system by their names.  Naturally, each
interface name has to be unique.  Although you may choose almost any name for
the new interface (as long as it does not exceed 15 characters and does not
contain spaces), interface naming should be consistent.  You may want to
incorporate device type, link type or georaphical location into the interface
name, so you won't forget what this interface is actually connected to.
ENDOFTEXT
	prompt "\nEnter interface name or hit [Enter] for the main menu: "
	[ "$CMD" ] && IF_NAME=$CMD
}

# ----------------------------------------------------------------------------
# Select IP address for the interface.
# ----------------------------------------------------------------------------
select_ipaddr()
{
	banner
	cat << ENDOFTEXT
Each interface must be assigned a uniqe IP address.  IP addresses are written
as four dot-separated decimal numbers from 0 to 255 (e.g. 192.131.56.1).
Usually this address is assigned to you by your network administrator or by
the Internet service provider.
ENDOFTEXT
	prompt "\nEnter IP addres for the interface $IF_NAME: "
	[ "$CMD" ] && IPADDR=$CMD
}

# ----------------------------------------------------------------------------
# Select netmask for the interface.
# ----------------------------------------------------------------------------
select_netmask()
{
	banner
	cat << ENDOFTEXT
Any IP address consists of two portions - network address and host address.
Usually, TCP/IP protocol stack can separate them by looking at the address
itself and deciding whether it belongs to address class A, class B or class C.

However, there are situations when you may want to override this (e.g. when
you create sub-nets within your particular address class).  In this case you
have to help TCP/IP stack to separate network and host portions of the IP
address by supplying a netmask.  Like the IP address, the netmask is written
as four dot-separated decimal numbers from 0 to 255 (e.g. 255.255.255.192).

If you don't need netmask, just hit [Enter].
ENDOFTEXT
	prompt "\nEnter netmask for the interface $IF_NAME: "
	[ "$CMD" ] && NETMASK=$CMD
}

# ----------------------------------------------------------------------------
# Select point-to-point address for the interface.
# ----------------------------------------------------------------------------
select_pointopoint()
{
	banner
	cat << ENDOFTEXT
Most WAN links are of point-to-point type, which means that there is only
one machine connected to the other end of the link and its address is known
in advance.  If peer address is not known, then it will have to be resolved
dynamically using inversed ARP or other protocol and must be supported by
both WAN driver and peer machine.

Like any other IP address, poit-to-point address is written as four
dot-separated decimal numbers from 0 to 255 (e.g. 192.131.56.2).

If you don't need point-to-point address, just hit [Enter].
ENDOFTEXT
	prompt "\nEnter point-to-point address for the interface $IF_NAME: "
	[ "$CMD" ] && POINTOPOINT=$CMD
}

# ----------------------------------------------------------------------------
# Select network routing the interface.
# ----------------------------------------------------------------------------
select_network()
{
	banner
	cat << ENDOFTEXT
The purpose of the WAN router is to connect your machine (or your local
network) to some other network or to the Internet.  In either case you have
to specify the address of the network you are connecting to, so that kernel
routing tables can be set up properly and all network traffic destined to
that network is directed to this interface.

Like any other IP address, network address is written as four dot-separated
decimal numbers from 0 to 255 (e.g. 192.131.56.0).  Alternatively, you can
use symbolic network name from the /etc/networks file in place of the numeric
address.

A special case is the network address 0.  This will create a default route,
meaning that all network traffic with no specific route found in the routing
table will be forwarded to this interface.  Default route is useful for
connections to the 'outside world', such as Internet service provider.

If you don't want to create a network route, just hit [Enter].
ENDOFTEXT
	prompt "\nEnter network address for the interface $IF_NAME: "
	[ "$CMD" ] || return 0
	NETWORK=$CMD

	banner
	cat << ENDOFTEXT
If the network you are connecting to is not directly reachebale, you may
also specify a gateway address.  Note however, that gateway has to be
reacheble, i.e. a static route to the gateway must exist.

Gateway address also follows usual IP address notation or can be replaced
with the symbolic name from the /etc/host file.

If you don't have a gateway, just hit [Enter].
ENDOFTEXT
	prompt "\nEnter gateway address for the network $NETWORK: "
	[ "$CMD" ] && GATEWAY=$CMD
}

# ----------------------------------------------------------------------------
# Create interface configuration file.
# ----------------------------------------------------------------------------
create_ifconf()
{
	cat << ENDOFTEXT > $IF_CONF
#!/bin/sh
# Router interface configuration file
# name:	$IF_NAME
# date:	`date`
#
ONBOOT=yes
IPADDR=$IPADDR
NETMASK=$NETMASK
POINTOPOINT=$POINTOPOINT
BROADCAST=$BROADCAST
NETWORK=$NETWORK
GATEWAY=$GATEWAY
ENDOFTEXT
}

# ----------------------------------------------------------------------------
# Remove interface configuration file.
# ----------------------------------------------------------------------------
del_interface()
{
	while
		banner
		get_iflist
		[ -z "$IFLIST" ] && {
			echo "No interface configuration files found!"
			pause ""
			return 0
		}
		echo -e "The following configuration files were found:\n"
		select_list $IFLIST
	do
		banner
		echo -e "You are about to delete configuration file $SEL\n"
		getyn "Are you sure" && rm $IFCONF_DIR/$SEL
	done
	return 0
}

# ----------------------------------------------------------------------------
# Show configured interfaces.
# ----------------------------------------------------------------------------
show_interface()
{
	while
		banner
		get_iflist
		[ -z "$IFLIST" ] && {
			echo "No interface configuration files found!"
			pause ""
			return 0
		}
		echo -e "The following configuration files were found:\n"
		select_list $IFLIST
	do
		banner
		[ -r $IFCONF_DIR/$SEL ] || {
			error "File $SEL not found"
			return 1
		}
		IPADDR=
		NETMASK=
		POINTOPOINT=
		BROADCAST=
		NETWORK=
		GATEWAY=
		. $IFCONF_DIR/$SEL
		show_ifconf $SEL
		pause ""
	done
	return 0
}

# ----------------------------------------------------------------------------
# Show interface configuration.
# ----------------------------------------------------------------------------
show_ifconf()
{
	echo "	Interface name:		$1"
	echo "	IP address:		${IPADDR:-"<none>"}"
	echo "	Net mask:		${NETMASK:-"<none>"}"
	echo "	Point-to-point address:	${POINTOPOINT:-"<none>"}"
	echo "	Broadcast address:	${BROADCAST:-"<none>"}"
	echo "	Network address:	${NETWORK:-"<none>"}"
	echo "	Gateway address:	${GATEWAY:-"<none>"}"
}

# ----------------------------------------------------------------------------
# Get list of configured interfaces.
# ----------------------------------------------------------------------------
get_iflist()
{
	IFLIST=
	tmp=`pwd`
	cd $IFCONF_DIR
	for i in *; do [ -r $i ] && IFLIST="$IFLIST $i"; done
	cd $tmp
}

# ----------------------------------------------------------------------------
# Main Menu.
# ----------------------------------------------------------------------------
main_menu()
{
	while
		echo -e "\t1) show interfaces"
		echo -e "\t2) add interface"
		echo -e "\t3) delete interface"
		echo -e "\th) help"
		echo -e "\tq) quit"
		prompt "\nPlease enter your selection (1..5, h or q) ->"
		case $CMD in
			1)	show_interface	;;
			2)	add_interface 	;;
			3)	del_interface	;;
			h|H)	show_help	;;
			q|Q)	clearscr; break	;;
		esac
	do banner; done
	return 0
}

# ----------------------------------------------------------------------------
# Show help.
# ----------------------------------------------------------------------------
show_help()
{
	clearscr
	cat << ENDOFTEXT | more
There is a number of configuration files associated with the WAN router.  They
are all ASCII (text) files and can be edited with any text editor, such as vi
or emacs.  However, if you are not experienced user, it is recommended that
you use this script to ensure proper syntax and prevent misconfigurations.

One of the configuration files is $ROUTER_RC.  It defines router operational
environment (e.g. location of the log file) and is used by the router start-up
script.  This file is created by the Setup script during the installation and
seldom needs to be changed.  Among other things defined in $ROUTER_RC is a
list of WAN drivers that are loaded automatically when router is started with
the 'router start' command.  You can add/remove drivers to/from the list by
selecting 'add driver' and 'delete driver' from the main menu.

Another configuration file is $ROUTER_CONF.  It is used by the wanconfig,
router configuration utility, to dynamicaly configure WAN device drivers and
create network interfaces.  Only a template is created during the installation
and you will have to edit this file according to the type of WAN media and
adapter you are using.  Because information contained in this file is mostly
hardware-specific, you will have to edit it manually.  Please refer to the WAN
Router User's Manual and WAN driver documentation for details.

The third group of configuration files is located in $IFCONF_DIR
directory.  These files are used by the router start-up script to configure
network interfaces at the TCP/IP level (i.e. IP address, netmask, etc.) and
set up static routes.  For each file found in $IFCONF_DIR
directory, start-up script will look for the interface with the same name and,
if one exists, configure it accordingly using ifconfig and route utilities.
Note that any network interface can be configured this way, not only those
created by the WAN router.

Although this feature is optional and may not handle very sofisticated cases,
it is quite useful, particularly if your router configuration includes dozens
of interfaces.  You can manage interface configuration files using this script
even without ever looking into $IFCONF_DIR directory or, if you
prefer, you can maintain them manually.
ENDOFTEXT
	pause ""
	return 0
}

# ----------------------------------------------------------------------------
# Remove temporary files, etc.
# ----------------------------------------------------------------------------
cleanup()
{
	rm -f $TMPFILE* 2> /dev/null
	return 0
}

# ----------------------------------------------------------------------------
# Display banner.
# ----------------------------------------------------------------------------
banner()
{
	clearscr
	echo -e "\t----------------------------------------------------------"
	echo -e "\t      Multiprotocol WAN Router Configuration Script"
	echo -e "\t    Copyright (c) 1995-1998, Sangoma Technologies Inc."
	echo -e "\t----------------------------------------------------------"
	echo ""
	return 0
}

###### MAIN ##################################################################
# set -x

export PATH=/sbin:/bin:/usr/sbin:/usr/bin
KERNEL=`uname -r`
ROUTER_VERSION=2.1.1
ROUTER_RC=/etc/wanrouter.rc
ROUTER_HOME=/usr/lib/wanrouter
IFCONF_DIR=$ROUTER_HOME/interfaces
MOD_DIR=/lib/modules/$KERNEL
SCRIPT=configure
TMPFILE="/tmp/T$$"
CMD=
SEL=

# Check user permissions.
[ "$UID" = 0 ] || {
	error "You must be a superuser to run this script"
	exit 1
}

# Read meta-configuration file.
[ -f $ROUTER_RC ] || {
	error "Configuration file $ROUTER_RC not found"
	exit 1
}
. $ROUTER_RC

# Set default configuration.
ROUTER_BOOT=${ROUTER_BOOT:=YES}
ROUTER_CONF=${ROUTER_CONF:=/etc/wanpipe/wanpipe1.conf}
ROUTER_LOG=${ROUTER_LOG:=/var/log/wanpipe}
ROUTER_LOCK=${ROUTER_LOCK:=/var/lock/wanpipe}
WAN_DRIVERS=${WAN_DRIVERS:="wanpipe"}

# Check lock file.
[ -f $ROUTER_LOCK ] && {
	error "Router appears to be running (lock file exists). Stop it first"
	exit 1
}

trap '' 2
banner
main_menu
cleanup
exit 0
