Skip site navigation (1)Skip section navigation (2)
Date:               Wed, 1 Feb 1995 12:28:03 -240
From:      "Pavlov's Cat" <Pavlov's.Cat>
To:        Michael Nelson <nelson@seahunt.imat.com>, Terry Rossi <tpr@picspc01.pics.com>, "Duane R. Ellison" <duane@qnet.com>, obiwan!bob@uudell.us.dell.com (Bob Willcox), dayton@sci.brooklyn.c
Cc:        questions@FreeBSD.org
Subject:         How-to: Connecting over PPP
Message-ID:  <m0rZivp-00008wC@infi.net>

next in thread | raw e-mail | index | archive | help
I'm honestly astonished by the number of requests that I have
received for my humble attempts at scripting the establishment,
monitoring, restarting and termination of a PPP client connection
under FreeBSD.  (I thought this info was in the
"Everybody-knows-that" category! :-)

Herewith are the procedures I used in a former life to get my dial-in 
connection running to my local Internet service provider.  I'm still 
using a subset of these scripts to automatically hook up my PPP link 
at home, but I see in the lists that folks are working on a 
demand-dial capability, so this may be obsolete by the time you read 
it.

NB: My local service provider uses a combination of Suns (for the 
terminal-based stuff) and NetBlazers (nice boxes, incidentally) for 
the actual connection and routing.  These scripts only connect to the 
NetBlazers, which then perform all of the routing from my lowly node 
to the rest of the world.   You may have to tweak the scripts 
slightly to hook into your local service provider because not all 
login procedures are created equal.

Things to note: 
   I assume that you have a modem installed and configured and the
appropriate /dev/~ entries.  If you can't fire up `kermit`, do a 'SET
LINE xxx',  'CONNECT' and throw "at" commands at the modem then
you'll have to dig thru the `sio` man page and the FAQ's to get to
this point.
   I assume that you've built a kernel with options GATEWAY so that the 
IP routing stuff is enabled.  This is not _strictly_ required for 
these scripts to work, but if you think that FreeBSD is going to gate 
your local network traffic to the whole-wide-world(tm) without 
rebuilding the kernel, then think again.
   I assume that you are using the `pppd` and (and companion `chat`)
programs from either 1.1.5 or the latest 2.0 snapshot.  (1.0, 1.1
and the initial 2.0 pppd's had problems and I never bothered to
sort 'em out.)  There are a couple of patches to the 'sio' stuff and
the pppd stuff that address the issues of proxy arp and hanging on
the cheap SMC dual-16550 UART's, but I haven't applied 'em; if
you're a stickler for detail, have at it.
   This 'FYI' only addresses the issues germane to using FreeBSD as a 
PPP client; I.E.: I'm not gonna tell you how to set up your FreeBSD 
box as a dial-in PPP server.  (I don't know how!)  I do know how to 
make your FreeBSD box a SLIP host, but that's another story.  Ask if 
you want the straight dope on doing that deed.
   These scripts work for me.  Your mileage may vary.

OK. Disclaimers aside, let's get busy.

First of all, we'll need to set up the comm & stty params when the 
system boots.  Other than getting SCSI stuff straightened out, this 
seems to be the biggest headache in FreeBSD-Questions, so here's how 
I do it.
I put the following lines in '/etc/rc.local' so they happen every 
time the system boots.  (I know there's an '/etc/rc.serial', but I 
confess that I don't understand it, and, anyway, I did this before 
rc.serial was part of the tree, so live with it.
I added the following lines down near the end of '/etc/rc.local':

=====  In /etc/rc.local ====
# Add the following lines near the end of /etc/rc.local to set the 
# comm params for the dial-in and dial-out lines

if [ -x /bin/stty ]; then
# Set up the PPP async port:
	comcontrol /dev/ttyd0 dtrwait 100	# may depend on modem
	# Lock crtscts on, Set speed reasonable for V42bis.
	/bin/stty -f /dev/ttyid0 crtscts hupcl 57600
	/bin/stty -f /dev/ttyld0 crtscts hupcl 57600
	/bin/stty -f /dev/cuai00 crtscts hupcl 57600
	/bin/stty -f /dev/cual00 crtscts hupcl 57600
	echo 'tty*00:  initialized @ 57600'
fi

if [ -x /bin/stty ]; then
# Set up the incoming async line.  Mostly used for dial-in terminals,
# but also appropriate for incoming SLIP clients:
	comcontrol /dev/ttyd1 dtrwait 100	# may depend on modem
	# Lock crtscts on, Set speed reasonable for V42bis.
	/bin/stty -f /dev/ttyid1 crtscts hupcl 57600
	/bin/stty -f /dev/ttyld1 crtscts hupcl 57600
	/bin/stty -f /dev/cuai01 crtscts hupcl 57600
	/bin/stty -f /dev/cual01 crtscts hupcl 57600
	echo 'tty*01:  initialized @ 57600'
fi

# To automagically establish the PPP connection, uncomment
# the following lines.  (Assumes that the `pppup` script exists!)
#if [ -f /etc/pppup ]; then
#	echo 'starting PPP'
#	rm -rf /var/spool/lock/*cua*
#	/bin/sh /etc/pppup &
#fi

# To start the PPP monitor at boot-up, uncomment the following
# lines.  (Again, the script file must exist!)
#if [ -f /etc/ip_monitor ]; then
#        /bin/sh /etc/ip_monitor &
#fi

echo 'exit rc.local.'
====================

Now that the I/O port is configured, we need a small script that will
bring the link up.  I use the 'pppd' and 'chat' programs to do this. 
Note that in this script you'll have to hard-code your own access ID
and password that your Internet service provider has issued to you. 
the "connect" stuff shown here is appropriate for the NetBlazer, but
if you're connecting to something else, like an "Annex" or
something, you'll have to tweak the params.  Should be intuitive.

I call the script '/etc/pppup' and it goes a little somethin' like this:

=====  /etc/pppup ====
#!/bin/sh

# Start a PPP Connection
# Copyright Steven J. Sims  SimsS@Infi.Net
# Freely distributable with copyright intact.

LOCKDIR=/var/spool/lock
DEVICE=cua00
SPEED=57600

if [ -f $LOCKDIR/LCK..$DEVICE ]
then
	echo "PPP device is locked - Sorry"
	exit 1
fi

# Fire that puppy up!
# Note 1: `pppd` might be in /usr/sbin under FreeBSD 2.x
#
# Note 2: All of the commands between the "'"'s (where the chat line is)
#        *must* be on the same line - 
#
# Note 3: The general syntax for the chat "script"ing is:
#		Send "A", Wait for: "B", Send "C", Wait for "D", etc...
#     So, we'll send an <Enter>, 
#		wait for a login prompt ("ogin:")
#		send our UserID
#		wait for a password prompt ("assword:")
#		send our password
#		wait for a command prompt ("ommand:")
#		send "ppp" to start the ppp service.
# Note 4:  Notice the use of the '\' continuation characters.  This 
# should | could be all on one line

/usr/libexec/pppd modem crtscts defaultroute connect \
'chat -l LCK..cua00 ABORT BUSY ABORT "NO CARRIER" "" ATDT123-4567 CONNECT "" "ogin:" "your_id" "assword:" "yourpass" "ommand:" "ppp"' \
netmask 255.255.255.0 /dev/$DEVICE $SPEED 198.22.1.39:198.22.1.109
#                                         ^^^^^^^^^^^^^^^^^^^^^^^^
# Note: The syntax shown above is only valid for fixed IP addresses!
# If the PPP service provider generates dynamic IP addresses, the IP address
# pair should be left off the end & pppd will figure out the right thing to do.

# End of pppup
====================

OK.  Now we can establish a connection.  So far, so good, but we'd
probably like to have an easy way to terminate it.  For this
purpose, I use a script I call '/etc/pppdown'.  It's pretty simple:

===== /etc/pppdown ====
#!/bin/sh

# Kill a PPP Connection
# Copyright Steven J. Sims  SimsS@Infi.Net
# Freely distributable with copyright intact.

LOCKDIR=/var/spool/lock
DEVICE=cua00
SPEED=57600

if [ -f $LOCKDIR/LCK..$DEVICE ]; then
	rm -rf $LOCKDIR/LCK..$DEVICE
fi

kill -TERM `ps -ax|grep pppd|grep -v grep|grep -v pppdown|awk '{print $1;}'`

echo 'PPP is down'

# End of pppdown
====================

That's as simple as it gets for getting the link up and down.  When
you feel the urge to merge on the Info-Bahn, just run (as 'root' or
equivalent) `sh /etc/pppup`.  When it's time to hit off-ramp for Gas, 
Food and Lodging, , run `sh /etc/pppdown`. Simple, huh?

On the subject of monitoring the status of the link.  I used to use
the following procedures to keep a 24-hour link up.  Where the system
was located, the phone circuits were _really_ bad, and I got tired of
the link going down and having to manually kick-start it every
couple of hours. Some of the SLIP scripts that I saw going around a
few months ago addressed this issue by telling the SLIP software how
to re-dial the connection, but I really had no success with SLIP (and
I'm a PPP bigot, anyway) so I cobbled up the following hacks to make
my system poll the link status and re-initiate the connection
whenever it died, often 20-30 times a day!
(As an aside, this works better than I had any right to expect; it'll
even resume FTP transfers in mid-stream once the line comes back up!)

Anyway - assuming that I've started the PPP client, I run the
following as a daemon script.  It runs every two minutes and checks
to see if any traffic has crossed the wire.  If not, it assumes that
the line is dead, and with a little voodoo majig, brings it back
from the dead.  (I've found that this method works because *my*
service provider sends RIP packets every 30 seconds or so, so there's
_always_ something going on across the link.  But in any event, I
force a one-shot ping to a remote system (on the other side of the
PPP link) every 60 seconds just to make sure.  Lots of people will
point out that this is /way/ overkill, and to them I respectfully
reply: "Hey, this works - leave me alone!" :-)

One last note before I show you the monitoring script:  You _could_
just run this out of '/etc/rc.local' (after setting the stty params
for the modem) instead of running the 'pppup' thingy - the only
caveat is that the link won't come up until 2 minutes after the
system boots because that's the scan interval between checks of the
link status; it takes two passes to determine that the link is dead.
There's probably a good way to work around this and have one
omni-function general purpose script that handles this, but I got
this working and moved on to something else...

OK - The '/etc/ip_monitor' script:
=====  /etc/ip_monitor ====
#!/bin/sh

# Monitor a PPP Connection, restarting if necessary
# Copyright Steven J. Sims  SimsS@Infi.Net
# Freely distributable with copyright intact.

LOCKDIR=/var/spool/lock
DEVICE=cua00
SPEED=57600
LOGFILE=/var/log/ip_monitor.log
INTERFACE=ppp0
SLEEPSECS=120

# For PPP clients that have static IP addresses (i.e.: both the
# local and remote addresses are always known), un-comment the
# following lines and fill in the known addresses.
# For dynamically assigned IP addresses, leave 'em blank or
# commented out.
# Note that there must be a colon (':') at the end of the LOCALIP
# number.
# This is the IP address of the local machine (the one I can kick)
#LOCALIP=192.68.1.1:
#
# This is the address of the machine at the other end of the
# phone line
#REMOTEIP=192.68.1.2


# Who can we ping periodically to see if the Ma Bell took a break?
#   (This may be in either hostname or dotted IP format)
PINGEE=my.good.friend

# Rotate the log files...
rm -f $LOGFILE.7
if [ -f $LOGFILE.6 ]; then mv -f $LOGFILE.6  $LOGFILE.7; fi
if [ -f $LOGFILE.5 ]; then mv -f $LOGFILE.5  $LOGFILE.6; fi
if [ -f $LOGFILE.4 ]; then mv -f $LOGFILE.4  $LOGFILE.5; fi
if [ -f $LOGFILE.3 ]; then mv -f $LOGFILE.3  $LOGFILE.4; fi
if [ -f $LOGFILE.2 ]; then mv -f $LOGFILE.2  $LOGFILE.3; fi
if [ -f $LOGFILE.1 ]; then mv -f $LOGFILE.1  $LOGFILE.2; fi
if [ -f $LOGFILE.0 ]; then mv -f $LOGFILE.0  $LOGFILE.1; fi
if [ -f $LOGFILE   ]; then mv -f $LOGFILE    $LOGFILE.0; fi

exec >$LOGFILE 2>&1 </dev/null
trap "" 1 2 3 13 15

echo "IP Monitor started at `date`"
echo Gateway is $LOCALIP
lastin=`netstat -n -I $INTERFACE |awk "/$LOCALIP/{print \\$5}"`
lastout=`netstat -n -I $INTERFACE |awk "/$LOCALIP/{print \\$7}"`
last=$lastin$lastout
echo Initial packet count is: $last

while true; do
   ping -c 1 -n -q $PINGEE > /dev/null
   sleep $SLEEPSECS
   lastin=`netstat -n -I $INTERFACE |awk "/$LOCALIP/{print \\$5}"`
   lastout=`netstat -n -I $INTERFACE |awk "/$LOCALIP/{print \\$7}"`
   inpackets=$lastin$lastout

   if [ $inpackets = $last ]; then
      # connection is dead...
      echo `date`: "Connection is dead."

      # slay the daemon
      kill -9 `ps -ax|grep pppd|grep -v grep|awk '{print $1;}'`

      # Nap a sec or three....
      sleep 2

      # Zap any lock files....
      if [ -f $LOCKDIR/LCK..$DEVICE ]; then
         rm -rf $LOCKDIR/LCK..$DEVICE
      fi

      # Jump-start that puppy  We should use the same params we
      # use in the /etc/pppup script.
      # Or, even better, we could shell that guy.  (See /etc/pppup for 
     # a description of how this works)

      /usr/libexec/pppd modem crtscts defaultroute connect \
         'chat -l LCK..cua00 ABORT BUSY ABORT "NO CARRIER" "" ATDT123-4567 CONNECT "" "ogin:" "your_id" "assword:" "yourpass" "ommand:" "ppp"' \
         netmask 255.255.255.0 /dev/$DEVICE $SPEED $LOCALIP:$REMOTEIP
      echo `date`: The pppd has been restarted.

# If you want to be nagged by mail every time the link cycles, uncomment
# the following line:
#     echo "pppd auto-restart @ `date`."|mail -s "PPP Restart" root
   else
# Un-comment the next line to log status line every time the link is
#   discovered to be up.  (This results in about 1,000 lines/day to the
#   log file:  Caveat Emptor.
#     echo `date`: Connection up, Count: $inpackets
      last=$inpackets
   fi
done

exit 0

# End of ip_monitor script
====================

The script above logs PPP status to '/var/log/ip_monitor.log' and it
can get pretty big after a while.  The log also has the disadvantage
of being hard to prune while the 'ip_monitor' script is running, so
I created another script (that gets called from `/etc/daily`) that
nukes the monitor, rotate the logs, and re-start the monitor just
like the 'maillog' logs get rotated. This is entirely optional, but
it does help in tracking the daily number of link failures and
provides some ammo to shoot at the phone company regarding their
cheesy phone lines.

 Here's what I added to '/etc/daily' to make the ip_cycle script run 
each day:

=====  In /etc/daily ====
# Add this line in /etc/daily to re-cycle the ip_monitor script
# every 24 hours.  This forces the log files to be coincident with 
# each days operations and, in general, keeps everything hunky-dory.

/bin/sh /etc/ip_cycle &

====================

And here's the script that cycles the ip_monitor logs:

===== /etc/ip_cycle =====
#!/bin/sh

# Recycles the IP_Monitor.
# Copyright Steven J. Sims  SimsS@Infi.Net
# Freely distributable with copyright intact.
#

# Where to stash the transcript:
OUTFILE=/tmp/ip_cycle_log

echo "" > $OUTFILE
echo "Cycling PPP Monitor @ `date`." >> $OUTFILE

# Find the PID for the running ip_monitor
PID=`ps -ax|grep ip_monitor|grep -v grep|awk '{print $1;}'`
echo "PID for ip_monitor was: $PID (before I tried to nuke it!)" >> $OUTFILE

# Frag it and pause:
kill -9 $PID >> $OUTFILE
sleep 5

# Start a new one:
/etc/ip_monitor &
sleep 5

# Report status:
PID=`ps -ax|grep ip_monitor|grep -v grep|awk '{print $1;}'`
echo "" >> $OUTFILE
echo "PID for ip_monitor is now: $PID" >> $OUTFILE
echo "" >> $OUTFILE
ps -ax >> $OUTFILE

# If you want the results of this reported by mail every morning,
# un-comment the following line:
#cat $OUTFILE | mail -s "IP Re-Cycle Results" root

# Lose the log
rm -f $OUTFILE

# End of ip_cycle script
=========================

So that's it.  I hope this helps get you connected to the 'Net.
I recognize that this is not the clearest description of how to do 
this, but I'm operating with the disadvantage of having built this 
stuff piecemeal; I assure you that there are some "important" things 
I've forgotten to include.  Ping me if you need clarification on any 
of this.

Even better, let me know how this scripting could be improved - 
you'll make a lot of other dial-up users *very* happy!

Warmest regards and the like....

--
...sjs...
Steve Sims                                            SimsS@Infi.Net                                    Virginia Beach, VA
Still working on a witty .signature...



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?m0rZivp-00008wC>