From owner-freebsd-questions Wed Feb 1 11:29:09 1995 Return-Path: questions-owner Received: (from root@localhost) by freefall.cdrom.com (8.6.9/8.6.6) id LAA05082 for questions-outgoing; Wed, 1 Feb 1995 11:29:09 -0800 Received: from infi.net (larry.infi.net [198.22.1.107]) by freefall.cdrom.com (8.6.9/8.6.6) with SMTP id LAA05067 for ; Wed, 1 Feb 1995 11:29:05 -0800 Received: from h-ecru.richmond.infi.net by infi.net with smtp (Smail3.1.28.1 #13) id m0rZivp-00008wC; Wed, 1 Feb 95 12:33 EST Message-Id: From: "Pavlov's Cat" Organization: Organized? Me? Hah! To: Michael Nelson , Terry Rossi , "Duane R. Ellison" , obiwan!bob@uudell.us.dell.com (Bob Willcox), dayton@sci.brooklyn.c Date: Wed, 1 Feb 1995 12:28:03 -240 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: How-to: Connecting over PPP Reply-to: SimsS@infi.net CC: questions@FreeBSD.org Priority: normal X-mailer: Pegasus Mail/Windows (v1.22) Sender: questions-owner@FreeBSD.org Precedence: bulk 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 , # 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 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...