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