#!/usr/bin/perl

my $doc = <<"EOT";

This script is for use with a Bigpond BP3-EXT (blue) USB nextG modem.

It was developed by Anthony Wesley on RedHat FC6, 1st March 2007. This script
has no attached copyright. Use it at your own peril. You can modify and redistribute
this script to suit your own requirements.

The modem is detected as a usb serial device, and responds to AT commands,
so it can be setup and operated just like an old fashioned analogue modem.

The PPP connection is only established between the host PC and the modem.
The modem establishes a separate connection to the nextG network that we 
do not see.  Thus you might see the PPP connection succeed even when the 
modem is in a location with no signal. Beware.

Another issue is that the modem cannot reliably tell us it's gateway 
address, so we have to determine this manually after the link is 
established using traceroute and then set it with the route command.

You need to have the following entries in /etc/ppp/options:

	lock
	usepeerdns
	noipx
	noauth
	nodetach
	debug
	user 'YOUR-USER-NAME@bigpond.com'
	/dev/ttyUSB1
	ipcp-accept-local
	ipcp-accept-remote

(some entries, e.g. "debug" are optional but useful. Remove it 
after it's working if you like)

and a valid /etc/ppp/chap-secrets, e.g.:


	# Secrets for authentication using CHAP
	# client	server	secret			IP addresses
	"YOUR-USER-NAME@bigpond.com"  "*"   "YOUR-PASSWORD"   "*"

Anthony Wesley
awesley@acquerra.com.au

EOT

#######################################################
#
# Set these locations according to your distribution
# hopefully you are using something that conforms to the
# LSB :-)
#
#######################################################

$LSUSB=		"/sbin/lsusb";
$LSMOD=		"/sbin/lsmod";
$INSMOD=	"/sbin/insmod";
$IFCONFIG=	"/sbin/ifconfig";
$ROUTE=		"/sbin/route";
$TRACEROUTE=	"/bin/traceroute";
$PPPD=		"/usr/sbin/pppd";
$KVERSION=	`/bin/uname -r`; chomp($KVERSION);
$MODULES_PATH=	"/lib/modules/$KVERSION";
$DMESG=		"/bin/dmesg";

#######################################################
#
# Set these for your modem. They are correct for the
# Telstra BP3-EXT (blue) USB nextG modem.
#
#######################################################
$NUMBER='*99#';
$VENDOR = "16d8";
$PRODUCT = "6280";

$USBDEVID = "$VENDOR:$PRODUCT";

######################################
#
# Wait for the device to be plugged in
#
######################################
while(1) {
   my $answer=`$LSUSB`;
   if (! grep /$USBDEVID/ , $answer) {
      print "Waiting for device to be plugged in...\n";
      sleep(2);
      }
   else {
      print "Found USB device $USBDEVID\n";
      last;
      }
   }

# is the module loaded? If not then load it
$answer=`$LSMOD`;
if (! grep /usbserial/, $answer) {
   my $cmd = "$INSMOD $MODULES_PATH/kernel/drivers/usb/serial/usbserial.ko vendor=0x$VENDOR product=0x$PRODUCT";
   print "[$cmd]\n";
   if (system($cmd)) {
 	print "Error running insmod. Aborted\n";
	Shutdown();
	}

   # wait for it
   sleep(2);

   # Check dmesg output
   open(I,"$DMESG |");
   my @lines = (<I>);
   close(I);
   @lines = splice(@lines,scalar(@lines)-10, 10);   # get the last 10 lines
   foreach my $line (@lines) {
      if ($line =~ /usb (\d+\-\d+): generic converter now attached to (ttyUSB\d+)/) {
	print "USB device connected to $1 as $2\n";
	++$count;
	}
      }
   close(I);

   if ($count < 3) {
      print "Warning: did not find expected messages in dmesg\n";
      }
   }

############################################
#
# ok, we're ready to rock and roll
#
############################################

# Start with fake addresses, we correct these later
my $cmd = "$PPPD 10.11.12.13:10.11.12.13 connect \"/usr/sbin/chat ABORT BUSY ABORT 'NO CARRIER' '' ATZ OK ATDT$NUMBER CONNECT\"";
print "[$cmd]\n";

###############################################
#
# fork and exec as /etc/ppp/options specifies 'nodetach'
#
###############################################
if (! ($pppd_pid = fork())) {
   exec($cmd);
   print "Launching pppd failed.\n";
   Shutdown();
   }

##############################################
#
# Wait for the ppp device to appear
#
##############################################
my $PPPDEV = "";
$now = time();
while(time() - $now < 10) {
   open(I,"$IFCONFIG |");
   my @lines = (<I>);
   close(I);
   if (($line) = grep /^ppp/ , @lines) {
	($PPPDEV) = $line =~ /^(ppp\d+)/m;
	last;
	}
   sleep(1);
   }

if (! $PPPDEV) {
   print "Could not find ppp device. Aborted\n";
   Shutdown();
   }
else {
   print "Using PPP device $PPPDEV\n";
   }

##################################################
#
# Now try and determine our default route. This is
# tricky as the modem doesn't tell us automatically
# so we use traceroute and discover for ourselves.
#
##################################################

my $GW = "";
if (! open(I,"$TRACEROUTE -n -m 2 10.11.12.13 |")) {
	print "Cannot run [$cmd]\n";
	Shutdown();
	}

while(my $line = <I>) {
   print "$line\n";
   if ($line =~ /\d\s+([\d\.]+)/) {
	$GW = $1;
	last;
	}
   }
close(I);

if ($GW) {
   print "Found gateway $GW\n";
   }
else {
   print "Could not determine gateway, traceroute failed\n";
   Shutdown();
   }

# Delete the default gateway
$cmd = "$ROUTE del default gw 0.0.0.0";
print "$cmd\n";
if (system($cmd)) { print "Command failed\n"; }

# Add a host route to our new gateway
$cmd = "$ROUTE add -host $GW dev $PPPDEV";
print "$cmd\n";
if (system($cmd)) { print "Command failed\n"; }

# Set this as the default
$cmd = "$ROUTE add default gw $GW";
print "$cmd\n";
if (system($cmd)) { print "Command failed\n"; }

# Remove the fake GW
$cmd = "$ROUTE del -host 10.11.12.13";
print "$cmd\n";
if (system($cmd)) { print "Command failed\n"; }

print "Finished\n";
exit 0;

sub Shutdown
	{
	kill(15,$pppd_pid) if $pppd_pid;
	system("$KILLALL chat");
	exit 1;
	}