#!/bin/sh
#
#   $Id: client-test,v 1.2 2006/02/13 23:50:44 quozl Exp $
#
#   client-test, PPTP lab test script
#   Copyright (C) 2005  James Cameron (quozl@us.netrek.org)
#
#   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.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# --
#
#   Creates many tunnels from a test client to a single server.
#   Test sequence is as follows
#
#   1.  on server ... set it to listen on chosen network address
#       ip addr add 10.9.0.3/16 dev eth0
#       and edit /etc/hosts.allow to cover range "ALL: 10.9.0.0/16"
#
#   2.  on client ... run pptpconfig to define a tunnel named test
#
#   3.  run "./client-test start" to create the tunnels
#
#   4.  run "./client-test status" to test the tunnels with ping
#
#   5.  run "./client-test stop" to stop the tunnels
#

# number of sets of tunnels to create
MAX_C=10

# number of tunnels in each set
MAX_D=100

# network address prefix for test network
PREFIX=10.9

# address of server on test network
SERVER=10.9.0.3

# create a virtual interface for the address
function if_up {
    ip addr add ${PREFIX}.${2}.${3}/16 dev eth0 && echo -n .
}

# delete the virtual interface
function if_down {
    ip addr del ${PREFIX}.${2}.${3}/16 dev eth0 2>/dev/null && echo -n .
# expected error on 2.6.8 ...
# RTNETLINK answers: Cannot assign requested address
}

# create a tunnel from the virtual interface to the server
function tu_up {
    pppd call test updetach linkname test-${1} \
        pty "pptp ${SERVER} --nolaunchpppd --localbind=${PREFIX}.${2}.${3}"
}

# create a tunnel from the virtual interface to the server
function tu_up_fast {
    pppd call test linkname test-${1} \
        pty "pptp ${SERVER} --nolaunchpppd --localbind=${PREFIX}.${2}.${3}"
    echo -n .
    sleep 0.1
}

# delete a tunnel previously created
function tu_down {
    if test -f /var/run/ppp-test-${1}.pid; then
	kill `head -1 /var/run/ppp-test-${1}.pid` && echo -n .
    fi
}

# start tunnels rapidly and fill up available memory until swap free
# starts to be scarce
function filler {
    if_up $1 $2 $3
    tu_up_fast $1 $2 $3
    swapfree=`grep SwapFree /proc/meminfo |awk '{print $2}'`
    until test ${swapfree} -gt 4096; do
	echo -n -
	sleep 1
    done
}

# check the state of a tunnel slot
function state {
    echo -n "slot ${1} "
    if ! test -f /var/run/ppp-test-${1}.pid; then
	echo -n "(missing) "
    else
	pid=`head -1 /var/run/ppp-test-${1}.pid`
	echo -n "pid ${pid} "
	if ! kill -0 ${pid} 2>/dev/null; then
	    echo -n "(missing) "
	fi
	iface=`tail -1 /var/run/ppp-test-${1}.pid`
	echo -n "iface ${iface} "
	if ! ip addr show dev ${iface} 1>/dev/null 2>/dev/null; then
	    echo -n "(missing) "
	fi
	inet=`ip addr show dev ${iface}|egrep --only-matching "inet [0-9.]*"|awk '{print $2}'`
	echo -n "inet ${inet} "
	peer=`ip addr show dev ${iface}|egrep --only-matching "peer [0-9.]*"|awk '{print $2}'`
	echo -n "peer ${peer} "
	avg=`/bin/ping -c 1 ${peer} 2>/dev/null | grep "rtt min" | cut -f6 -d/`
	if test -z "${avg}"; then
	    echo -n "ping (missing) "
	else
	    echo -n "ping ${avg} "
	fi
    fi
    echo
}

# general purpose iteration function to call a handler (above) once
# for each slot in the test set.  Handler receives slot number, then
# the fragments of IP address a.b.C.D.
function iterate {
    x=1
    for c in `seq ${MAX_C}`; do
	for d in `seq ${MAX_D}`; do
	    ${1} ${x} ${c} ${d}
	    x=`expr ${x} + 1`
	done
    done
}

# start the test
function start {
    iterate if_up
    echo
    iterate tu_up
    echo
}

# start slow test
function fill {
    iterate filler
    echo
}

# stop the test
function stop {
    iterate tu_down
    echo
    sleep 10
    iterate if_down
    echo
}

# check status of test
function status {
    iterate state
}

# main dispatcher
case "$1" in
    start)
	start
	break
    ;;
    fill)
	fill
	break
    ;;
    stop)
	stop
	break
    ;;
    restart)
	stop
	start
	break
    ;;
    status)
        status
	break
    ;;
    *)
	echo "Usage: ${0} start|fill|stop|restart|status" 1>&2
	exit 1
    ;;
esac

