Return to BSD News archive
Path: sserve!manuel.anu.edu.au!munnari.oz.au!hp9000.csc.cuhk.hk!saimiri.primate.wisc.edu!zaphod.mps.ohio-state.edu!cs.utexas.edu!swrinde!elroy.jpl.nasa.gov!usc!news!netlabs!lwall
From: lwall@netlabs.com (Larry Wall)
Newsgroups: comp.unix.bsd
Subject: Re: 386BSD SLIP support
Message-ID: <1992Dec8.005248.24703@netlabs.com>
Date: 8 Dec 92 00:52:48 GMT
References: <3863@news.cerf.net> <RICH.92Dec1165100@omicron.Rice.edu>
Sender: news@netlabs.com
Organization: NetLabs, Inc.
Lines: 394
Nntp-Posting-Host: scalpel.netlabs.com
In article <RICH.92Dec1165100@omicron.Rice.edu> Rich@rice.edu writes:
: In article <3863@news.cerf.net> lewis@nic.cerf.net (Lewis Jr. High) writes:
: I know that 386BSD supports SLIP, but is there any way to command the
: modem to dial a terminal server and log in with a username and password to
: get the SLIP session started?
:
: Jeff
:
: You can use kermit scripts or tip. Send me mail if you want an
: example kerit script.
:
: expect and other utilties are included with various ppp
: implementations.
:
: We really need a utility that will reconnect a slip line when the line
: hangs for various reasons. Some of that support could be written into
: slattach, but alot of it could be done with a perl script alone. Rich
You mean, like this?
Larry
#!/bin/sh
: make a subdirectory, cd to it, and run this through sh.
echo 'If this kit is complete, "End of kit" will echo at the end'
echo Extracting slipup
sed >slipup <<'!STUFFY!FUNK!' -e 's/X//'
X#!/usr/bin/perl
X#
X# configuration variables
X#
X$tty = "cua0";
X$debug = 0;
X$timeout = 60;
X$delay = 2;
X$verbose = 0;
X$phone = "95554321";
X$login = "MYLOGIN";
X$passwd = "MYPASSWORD";
X$network = "128.145";
X$idletime = 600;
X$threshold = 20;
X$busysleep = 10;
X$busyretries = 5;
X$LCKDIR = '/var/spool/locks';
X
X$ENV{PATH} = '/usr/bin:/etc:/usr/etc';
X
X# initialzation
X
X$network =~ s/\./\\./g;
X$user = (getpwuid($<))[0];
X
Xrequire "sys/ttold.ph";
Xrequire "getopts.pl";
Xrequire "syslog.pl";
X&openlog("slipup $user", 'pid,cons,ndelay', 'daemon');
X
X#
X# process arguments
X#
X&Getopts('dvr:s:k:');
X$debug = 1 if defined $opt_d;
X$verbose = 1 if defined $opt_v;
X$busyretries = $opt_r if defined $opt_r;
X$busysleep = $opt_s if defined $opt_s;
X$KEEPTILL = time + $opt_k * 3600 if defined $opt_k;
X
Xeval '&main';
X&CLEANUP($@);
Xexit 1;
X
Xsub CLEANUP {
X local($arg) = @_;
X
X if ($arg) {
X $0 = "slipup ($arg)";
X warn "\n".$arg;
X &syslog(WARNING, $arg);
X }
X else {
X $0 = "slipup (shutting down normally)";
X }
X if ($sequencenumber) {
X $sequencenumber = 0;
X $SIG{ALRM} = CLEANUP;
X alarm(15);
X shutdown(ECHO,2);
X close ECHO;
X alarm(0);
X }
X kill 'TERM', $pid if $pid;
X if ($ttyopen) {
X system "stty 0";
X close STDIN;
X close STDOUT;
X system "/bin/stty 0 >/dev/$tty";
X }
X unlink "$LCKDIR/LCK..$$";
X if ($locked) {
X system("/usr/etc/route -f") && warn "route flush failed\n";
X unlink "$LCKDIR/LCK..$tty";
X }
X exit length($arg) != 0;
X}
X
Xsub SIGALRM { die "SIGALRM: ECHO timed out\n"; }
Xsub SIGPIPE { die "SIGPIPE: ECHO closed other end\n"; }
X
Xsub main {
X #
X # grab the line
X #
X $0 = "slipup (locking $tty)";
X if (`/usr/ucb/netstat -i -n` =~ /$network/) {
X warn "Slip line is already up\n" if $verbose;
X exit 0;
X }
X warn "Opening /dev/$tty...\n" if $verbose;
X die "$tty is busy\n" if -e "$LCKDIR/LCK..$tty";
X open(LCK, ">$LCKDIR/LCK..$$") || die "Can't create lock: $!\n";
X printf LCK "%10d\n", $$;
X close LCK;
X die "$tty is busy\n" unless link("$LCKDIR/LCK..$$", "$LCKDIR/LCK..$tty");
X unlink "$LCKDIR/LCK..$$";
X $locked++;
X $0 = "slipup (opening $tty)";
X die "$tty is not a tty\n" if ! -c "/dev/$tty";
X die "Cannot open $tty: $!\n" if !open(STDOUT, "+>/dev/$tty");
X $ttyopen++;
X die "Cannot dup STDOUT to STDIN\n" if !open(STDIN, "+<&STDOUT");
X &syslog("Can't ioctl(TIOCEXCL) on $tty: $!")
X unless ioctl(STDOUT, &TIOCEXCL, 0);
X
X $SIG{'INT'} = 'INTR_HAND';
X $SIG{'HUP'} = 'INTR_HAND';
X $SIG{'QUIT'} = 'INTR_HAND';
X $SIG{'TERM'} = 'INTR_HAND';
X $SIG{'USR1'} = 'UNDEBUG';
X
X #
X # configure the line
X #
X die "stty failed\n" if system "/bin/stty 19200 raw -echo min 1 time 0";
X
X $| = 1;
X
X #
X # dial the modem
X #
X $0 = "slipup (dialing $tty)";
X warn "Dialing modem...\n" if $verbose;
X #&send("ATE1V1X2Q0S2=0S58=2S68=2S48=1S50=6S51=5S94=0S180=2S181=1S190=4\r\n");
X &send("ATE1V1X2Q0S2=0S58=2S68=2S48=1S50=6S51=5S94=0S180=2\r\n");
X &wait_for("OK");
X &send("ATDT$phone\r");
X $countdown = $busyretries;
X while (&wait_pat("(BUSY|CONNECT|CARRIER)") ne 'CONNECT') {
X $tries = $countdown . ($countdown == 1 ? " try" : " tries");
X $0 = "slipup (redialing $tty, $tries left)";
X die "BUSY\n" if $countdown <= 0;
X warn "BUSY--trying again in $busysleep seconds, $tries left\n" if $verbose;
X $countdown--;
X &send("ATH\r");
X sleep $busysleep;
X &send("ATDT$phone\r");
X }
X
X #
X # log into the terminal server
X #
X $0 = "slipup (logging in on $tty)";
X warn "Logging in...\n" if $verbose;
X &send("\r"); sleep($delay);
X &send("\r"); sleep($delay);
X &send("\r"); sleep($delay);
X &send("\r"); sleep($delay);
X &send("\r"); sleep($delay);
X &wait_for("name:");
X &send("$login\r");
X &wait_for("ssword:");
X &send("$passwd\r");
X &wait_for("ts>");
X
X #
X # start slip
X #
X $0 = "slipup (starting slip on $tty)";
X warn "Starting slip...\n" if $verbose;
X &send("slip\n");
X $_ = &wait_pat("Your IP address is .* MTU is 1500 bytes");
X die "Cannot find slip address\n"
X if !/Your IP address is (\d+\.\d+\.\d+\.\d+),/;
X $addr = $1;
X $0 = "slipup (starting slip on $addr)";
X die "stty failed\n" if system "/bin/stty crtscts";
X die "route flush failed\n" if system "/usr/etc/route -f >/dev/null";
X
X $ppid = $$;
X if (fork) {
X $SIG{HUP} = EXIT;
X sleep 1 while 1;
X }
X $SIG{'TSTP'} = 'IGNORE';
X
X if (!($pid = fork())) {
X $< = $>;
X warn "/usr/etc/slip-attach /dev/$tty 19200 $addr $addr 255.255.0.0\n" if $debug;
X exec "/usr/etc/slip-attach /dev/$tty 19200 $addr $addr 255.255.0.0";
X die "Couldn't exec slip-attach: $!\n";
X }
X $0 = "slipup (adding route for $addr)";
X sleep 2;
X if (`/usr/bin/ps auxww` =~ /root *(\d+).*slip-attach/) {
X $pid = $1;
X }
X else {
X $pid++;
X }
X die "route add default failed\n"
X if system "/usr/etc/route add default $addr 1 >/dev/null";
X warn "slip is up: process $pid, local address $addr\n" if $verbose;
X &syslog(NOTICE, "started $pid on $tty, address $addr");
X
X $SIG{'INT'} = 'IGNORE';
X $SIG{'HUP'} = 'IGNORE';
X $SIG{'QUIT'} = 'IGNORE';
X kill 'HUP', $ppid;
X sleep 1;
X kill 'KILL', $ppid;
X
X #
X # now loop forever waiting for an idle line
X #
X
X setpgrp(0,$$);
X sleep 2;
X `/usr/ucb/netstat -i -n` =~ /(slip|stream)\d*\s*\d*\s*$network[.\d]*\s*[.\d]*\s*(\d*)/;
X $lasti = $2;
X warn "input: $lasti\n" if $debug;
X
X &getsock(ECHO, $addr, 'tcp', 'echo');
X $SIG{PIPE} = SIGPIPE;
X
X while (1) {
X $KEEPTILL = 0 if time > $KEEPTILL;
X if ($KEEPTILL) {
X $tmp = sprintf("%4.2f", ($KEEPTILL - time) / 3600);
X $0 = "slipup (monitoring $pid--keeping $tmp more hours)";
X }
X else {
X $0 = "slipup (monitoring $pid for $addr)";
X }
X
X sleep $idletime;
X
X print ECHO ++$sequencenumber, "\n";
X $SIG{ALRM} = SIGALRM;
X alarm(60);
X $echoed = <ECHO>;
X alarm(0);
X $echoed == $sequencenumber || die "ECHO sequence mismatch\n";
X
X unless (kill 0, $pid) {
X system "/usr/etc/route -fn >/dev/null 2>&1"
X || &syslog(WARNING, "route flush failed\n");
X &CLEANUP("slip-attach for $network [$pid] died!\n");
X }
X $_ = `/usr/ucb/netstat -i -n`;
X ($slipstream, $i)
X = /(slip|stream)\d+\s+\d+\s+$network[.\d]*\s+[.\d]+\s+(\d+)/;
X unless ($slipstream) {
X system "/usr/etc/route -fn >/dev/null 2>&1"
X || &syslog(WARNING, "route flush failed\n");
X &CLEANUP("slip interface for $network disappeared!\n");
X }
X $diff = $i - $lasti;
X $lasti = $i;
X warn "input: $diff, seqnum: $echoed\n" if $debug;
X if ($diff < $threshold && time > $KEEPTILL) {
X $0 = "slipup (idlekilling pid $pid)";
X kill 'TERM', $pid;
X sleep 3;
X kill 'KILL', $pid;
X system "/usr/etc/route -fn >/dev/null 2>&1"
X || die "route flush failed\n";
X &syslog(NOTICE, "idle shutdown ($diff/$threshold)");
X warn "Idle too long--shutting down slip\n" if $verbose;
X &CLEANUP("");
X }
X }
X}
X
Xsub get_char {
X local($rmask, $nfound, $timeleft, $thisbuf);
X $endtime = time + $timeout;
X $rmask = "";
X vec($rmask,fileno(STDIN),1) = 1;
X ($nfound, $timeleft) = select($rmask, undef, undef, $endtime - time);
X if ((0 + $endtime - time) <= 0) {
X die "Timed out\n";
X }
X if ($nfound) {
X $nread = sysread(STDIN, $thisbuf, 1024);
X if (defined($nread)) {
X print STDERR $thisbuf if $debug;
X $str .= $thisbuf;
X return "" if $nread == 0; # eof
X }
X } else {
X return undef; # timeout ?
X }
X}
X
Xsub wait_for {
X local($pattern);
X
X warn "WAITING FOR:\n\n$_[0]\n\n" if $debug;
X
X ($pattern = $_[0]) =~ s/(\W)/\\$1/g;
X while (1) {
X if ($str =~ /$pattern/) {
X $str = $';
X return $&;
X }
X &get_char;
X }
X}
X
Xsub wait_pat {
X warn "WAITING FOR PATTERN:\n\n$_[0]\n\n" if $debug;
X
X while (1) {
X if ($str =~ /$_[0]/) {
X $str = $';
X return $&;
X }
X &get_char;
X }
X}
X
Xsub send {
X local ($send) = @_;
X
X warn "SENDING:\n\n$send\n\n" if $debug;
X print "$send";
X}
X
Xsub INTR_HAND {
X &CLEANUP("Received SIG$_[0]--aborting...\n");
X}
X
Xsub UNDEBUG { $debug = !$debug; warn "debug = $debug\n" if $verbose; }
X
Xsub EXIT { exit 0; }
X
Xsub getsock {
X local($SOCK, $SERVER, $PROTO, $PORT) = @_;
X
X $pat = 'S n C4 x8';
X
X $af_unix = 1;
X $af_inet = 2;
X
X $stream = 1;
X $datagram = 2;
X
X local($name,$aliases,$proto) = getprotobyname($PROTO);
X
X local($name,$aliases,$port,$proto) = getservbyname($PORT,$PROTO);
X
X if ($SERVER =~ /^\d+\./) {
X @bytes = split(/\./,$SERVER);
X }
X else {
X ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($SERVER);
X die "Can't lookup $SERVER\n" unless $name;
X @bytes = unpack("C4",$addrs[0]);
X }
X
X $this = pack($pat,$af_inet,0, 0,0,0,0);
X $that = pack($pat,$af_inet,$port,@bytes);
X
X socket($SOCK,$af_inet,$stream,$proto) || die "socket: $!\n";
X bind($SOCK,$this) || die "bind: $!\n";
X connect($SOCK,$that) || die "connect to @bytes $port: $!\n";
X select((select($SOCK), $| = 1)[0]);
X 1;
X}
!STUFFY!FUNK!
echo ""
echo "End of kit"
: I do not append .signature, but someone might mail this.
exit