
PPP for Linux                                             Version 0.1.4
============= 

Warning: this code may crash your machine and corrupt your disk.  Use
at your own risk!

Actually, lots of people are using the code now and I've not heard of
one crash, but it still pays to be careful.

Disclaimer: the code is still a bit unclean. 

[If you used a previous version, you can skip to the sections at the
end entitled UPDATING FROM N.N.N.]

INTRODUCTION

This is an alpha version of a PPP driver for Linux.  It works reliably
for me and I use it all the time.  I have moved more than 20 megabytes
of data over a 9600 baud link to and from my PC, which is an old 16mhz
386sx with 4 MB of RAM.  It survives in the face of serial overruns
caused by more slowpoke processor and lame 16450 serial chip, and it
has never crashed.  Lots of people seem to be using it successfully
now, so it's very near a beta release.

The PPP protocol consists of two parts.  One is a means for framing
and encoding packets, the other is a series of protocols called LCP,
IPCP, UPAP and CHAP, for negotiating link options and bringing the
link into a functioning state and for authentication.  This package
similarly consists of two parts: a kernel module (drivers/net/ppp.c)
which handles PPP's low-level framing protocol, and a user-level
program called pppd which implements PPP's negotiation protocols.

The kernel module assembles/disassembles PPP frames, handles error
detection, and forwards packets between the serial port and either the
kernel network code or the user-level program pppd.  IP packets go
directly to the kernel network code.  So once pppd has negotiated the
link, it in practice lies completely dormant until you want to take
the link down, when it negotiates a graceful disconnect.

I wrote the kernel module from scratch.  Laurence Culhane and FvK's
slip.c was priceless as a model (a perusal of the files will reveal
that I often mimicked what slip.c did).  Otherwise I just implemented
what pppd needs, using RFC1331 as a guide.

pppd comes from the package pppd-1.3.1.  The most serious degredation it
has had to suffer in the port to Linux is Linux's lack of support for
asynchronous I/O.  I've hacked an ioctl into the ppp kernel module
that provides a signal when packets appear.  It's a gross work-around
but it works, for the time being.  

With the major exception of supporting dialup-IP (that is,
automatically taking the link up and down based on usage), the code
now does everything I want it to.  Now is the time for other people to
try it wholeheartedly.

Thanks to all who tried out 0.0.1!


INSTALLATION

This assumes you haven't already installed version 0.0.1.  If you
have, skip to UPDATING FROM 0.0.1.

First, you need the alpha pl13p kernel.  Maybe it will work with
earlier kernels (probably so) but I don't know.  It probably works
with later kernels, but I've not tried that yet.  Of course you also
need ifconfig/route/netstat/telnet etc that work with this kernel.

Kernel installation: 

      'pl13p.patches' contain patches from Alan Cox that appeared on
      the NET channel.  These are needed *only* if you're still using
      pl13p and haven't installed the patches already.  By this point
      almost everyone is using more recent kernels, or should be.

      'pl13pqrs.patches' contain patches that add the PPP driver to the
      miscellaneous configuration files (config.in,
      drivers/net/{Space.c,Makefile}).  If you're using pl13t or
      later, you don't need this.
   
      'serial.patches' contains appropriate patches to
      drivers/char/serial.c and include/linux/tty.h to report receiver
      overruns better.  Strictly speaking, this is optional, but if
      you have serial overruns they won't be reported correctly
      without this patch.
  
      Note that, unfortunately, the serial code patch modifies
      include/linux/tty.h, which means lots of files will want to be
      recompiled.  Actually only drivers/char/serial.c uses the
      manifest constants I defined in this header file, so you could
      just put the constants in serial.c and save yourself some time.
      (On my machine, compiling is slow enough to make this dodge
      worthwhile.)  I leave this as an exercise for the reader.

      ppp.c and ppp.h are the driver itself.

      To install, go to the linux source directory and perform three 
      steps:
         1) apply the patches you need:
              pl13p without Alan Cox fixes:
                   pl13p.patches, pl13pqrs.patches, serial.patches
	      pl13p with Alan Cox fixes already in, or pl13q...pl13s:
                   pl13pqrs.patches, serial.patches
              pl13t:
                   serial.patches, and REMOVE the '#' in front of the
                   PPP line in config.in (!!!)
              pl14:
                   same as pl13t
            to apply patches, go to the top directory of the Linux
            kernel source and type "patch -p0 < whatever.patches"
         2) copy ppp.c to drivers/net/ppp.c
         3) copy ppp.h to include/linux/ppp.h

      Now reconfigure and recompile as per the kernel instructions.
      Amongst the files that are compiled should be ppp.c, which
      should compile without error.

      REMEMBER TO SAVE A KERNEL THAT YOU KNOW WORKS!  (I hope I don't
      need to say this.)

      Reboot with the new kernel.  You should see a message on startup
      saying there are 4 PPP channels.  

pppd installation:

      Unpack the tar file.  Type 'make'.  I don't have a Linux machine
      at the moment, so there's no executable in the tar file.

      pppd needs to be run as root.  You can either make it suid root
      or just use it as root yourself.

      That's all there is to installing pppd, unless (heaven forfend)
      you want to try the untested support for UPAP or CHAP.  In that
      case I'd be interested in hearing how it turns out, but you'll
      have to consult the manpage and UTSL to see how to make it go.

network configuration:

      Your /etc/rc.net should 'ifconfig' the loopback interface lo,
      and should add a route like this:
	$ROUTE add loopback
      However, it should *not* config an ethernet card (unless you
      actually have one, in which case I'll assume you know what to
      do).  It should not install any other routes; as distributed
      it is likely to try to set up a route for the ethernet interface
      and a default route directing packets to the Ethernet.  You
      don't want this.  After booting, running 'netstat -nr' should
      reveal exactly one route, like this:
Kernel routing table
Destination net/address   Gateway address           Flags RefCnt    Use Iface
127.0.0.1                 *                         UH         0      0 lo

      I can't cover all the details of network configuration, but two
      issues come to mind.  First, you should decide whether you want
      to allow incoming telnet/ftp/finger, etc; if so, you should run
      inetd.  Second, you should put appropriate things in your
      /etc/resolv.conf .      


USING PPP

The very first test is to type
	cat /proc/net/dev
You should see four ppp channels listed, like this:
Inter-|   Receive                  |  Transmit
 face |packets errs drop fifo frame|packets errs drop fifo colls carrier
    lo:      0    0    0    0    0        0    0    0    0     0    0
  ppp0:      0    0    0    0    0        0    0    0    0     0    0
  ppp1:      0    0    0    0    0        0    0    0    0     0    0
  ppp2:      0    0    0    0    0        0    0    0    0     0    0
  ppp3:      0    0    0    0    0        0    0    0    0     0    0

This shows that ppp has made it into the kernel.

Now, let's try using pppd in a minimal way.  Type

      pppd debug x.x.x.x:y.y.y.y 

where x.x.x.x is your IP address and y.y.y.y is some other IP address.
This will start up pppd and instruct it to negotiate a PPP connection
with whoever might be attached to stdin/stdout.  (It will expect the
other machine to use IP address y.y.y.y .)  Since what is connected is
you, what will happen is that pppd will spit some nonsense your way
and eventually give up.  If things are set up properly, you should see
a series of messages from ppp_ioctl about various things, and then
about six full lines of things like "!}!}!} }2}!".  After that you
should get your shell prompt back.  At this point you know that the
line discipline works and pppd is minimally functional.

Incidentally, pppd will write error messages to syslog.  Depending on
your configuration you may need to look at /usr/adm/messages to see
pppd's errors.  If pppd exits without apparently doing anything, you
should definitely consult /usr/adm/messages.

Now, how to use PPP for *actual* communication depends on how you
connect.  You should probably consult the manpage.  

Probably the right thing to do is to get the "chat" package compiled
by Al Longyear.  It contains scripts that will dial a PPP server, log
in, and run pppd.  You can get it from sunsite (look in
system/Network) or I may try to put a copy on my ftp sites.  At the
moment, I don't have any experience using chat, but it is clearly the
Right Thing To Do, and everyone else seems to use it happily enough.

On the other hand, if you want to test PPPD in a way that lets you
dial "manually", do this:  (this is what I do)

- start Kermit
- issue these Kermit commands, or analogous ones appropriate for your
  configuration: 
	set line /dev/ttyS0
	set baud 9600
	set term byte 8
	set parity none
- type 'connect' and use your modem or whatever to connect to your PPP
  server
- once your PPP server is waiting for your machine to open a PPP
  connection, escape to kermit command mode using "ctrl-] C" or
  whatever your escape character is, then type at the C-Kermit> prompt
	!pppd -am defroute debug -detach /dev/ttyS0
  The meaning of the options is:
	-am	don't negotiate asyncmap: quote all control characters
	defroute  once the link comes up, install it as the default route
	debug	write verbose messages to /usr/adm/messages
	-detach	don't run as a background daemon
	/dev/ttyS0   obvious

Previously, pppd would hang up the line when it started.  I hope I've
fixed it so that it will only do that now if you give the 'dropdtr'
option on the command line.  At long last, this bug may actually be
quashed (in pppd version 0.1.4).

Meanwhile, a work-around is to tell your modem to ignore DTR and so
not to drop the line when DTR goes down.

    [Note: the previous suggested work-around, involving redirection,
    was a total crock.  If you heard about it, ignore it.]

Anyway, assuming your connection is working, you should see a series
of messages something like this:

	ppp: channel ppp0 open
	ppp_ioctl: set flags: flags 0
	ppp_ioctl: set flags: flags 0
	ppp_ioctl: set flags: flags 1
	ppp_ioctl: set flags: flags 3
	ppp: channel ppp0 going up for IP packets!
	ppp_ioctl: set flags: flags 7

Simultaneously, pppd is also writing interesting things to
/usr/adm/messages.  

IF IT WORKS

If you think you've got a connection, there are a number of things you
can do to test it.

First, type
	/usr/etc/ifconfig
This should show you all the network interfaces that are 'UP'.  ppp0
should be one of them, and you should recognize the first IP address
as your own and the "POINT-TO-POINT ADDR" as the address of your
server.

Now, type
	ping z.z.z.z
where z.z.z.z is the address of your server.  This should work.

Try typing:
	netstat -nr
This should show three routes, something like this:
Kernel routing table
Destination net/address   Gateway address           Flags RefCnt    Use Iface
default                   163.1.35.9                UGN        0   1037 ppp0
127.0.0.1                 *                         UH         0      0 lo
163.1.35.9                *                         UH         0      1 ppp0

Here, 163.1.35.9 is the address of my PPP server.  If your output
looks similar but doesn't have the 'default' line, you may have run
pppd without the 'defroute' flag.

At this point you can try telnetting/ftping/fingering whereever you
want, bearing in mind that you'll have to use numeric IP addresses
unless you've set up your /etc/resolv.conf correctly.

IF IT DOESN'T WORK

If you don't seem to get a connection, try again, adding the
"kerndebug n" option to the pppd command line.  This turns on 
debugging in the kernel PPP driver to level n.  Level 4 is useful: it
will produce lots of messages about activity on the ppp line.  Some
messages to be aware of:
   ppp_write: <count>,FF,3,C0,21,data,data,data...
This is pppd sending a packet to try to begin negotiation.
   ppp: got <count>.data.data.data...
This is a frame from the PPP server.  At the start, frames should all
begin with "ff.3.c0.21".
   ppp: got <0>
is a special case of the previous message: it means a "end-of-packet"
character has been received immediately following another one and just
says that the remote server is being conservative and sending
end-of-packet characters before packets, too.
   ppp_toss: tossing frame, reason = 4
The PPP code is throwing away a packet ("frame") from the remote
server because of a serial overrun.  (Other 'reasons' are possible
too, for different problems.)

Send me mail with whatever logs and information you can muster.

TO DO

   - clean up code!
   - try to improve interrupt response for slow computers (not sure if
     this is possible, actually--the code doesn't run with interrupts
     off very much)
   - test UPAP/CHAP
   - add support for 'dialup IP' (ie automatic connect/disconnect)
   - describe how to do a cache-only nameserver


UPDATING FROM 0.0.1

Updating the kernel is simple.  You can ignore the two '.patches'
files since you've already got the patches in place.  All you have to
do is 
  - replace drivers/net/ppp.c with the 0.1.3 version
  - DELETE drivers/net/ppp.h
  - move ppp.h from the 0.1.3 distribution to include/linux
Then remake...

Updating pppd is even easier: throw away the old one and get the new.

You might want to re-read the rest of this document anyway, especially
the part about network configuration.

Briefly, what's new:
 - VJ TCP header compression works, at least for me (I use it all the
   time)
 - pppd updated to the version from ppp-1.3.1; this should fix some
   bugs in the negotiation code that cause infinite loops with other
   implementations
 - pppd will always put in a host route to the PPP server when the 
   link comes up (see also the 'defroute' option below)
 - new options to pppd:
	dropdtr		hangup phone at start; I *think* I've got it
			so pppd will never hang up unless this option
			is specified
	kerndebug n	set the PPP kernel module to debugging
			verbosity n
	defroute	make this ppp link the default route once it
			comes up

Note the documentation bug described below.

UPDATING FROM 0.1.2:

The only code change is in the kernel module ppp.c.  In fact, there's
just one added line of code, to reset the IFF_POINTOPOINT flag each
time a ppp interface goes up.  Otherwise, the flag is cleared on the
first close.  This affects people whose local and remote IP addresses
have different network values, and the symptom is that the first ppp
connection works but subsequent ones have routing problems.

The fix is to replace ppp.c with the supplied one, and recompile the
kernel.

The only other change from 0.1.2 to 0.1.3 is a fix to this document 
to remove a mistaken suggestion that you use redirection to avoid the
dropping-DTR problem.  Here's the scoop:

MAJOR DOCUMENTATION BUG: In previous versions of this document and
elsewhere, I recommended a work-around for the pppd-dropping-dtr
problem involving redirection of stdin and stdout.  I don't think this
worked or could ever have worked, as a consultation of the code
shortly reveals.  Thanks to Al Longyear for showing me the nose in
front of my face.  I don't know where my brain was when I thought I
verified that this worked, but anyway I apologize for the misleading
and useless recommendation.  To quote the immortal words of Nixon's
press secretary Ron Ziegler, "That statement is no longer operative."
(Of course, Nixon had actually been lying; I just didn't know what I
was talking about...)


UPDATING FROM 0.1.3:

There are two changes from 0.1.3.  One is that I've repackaged the
kernel patches so people with pl13t and later kernels can use them.
The other is that I've finally fixed the DTR bug in pppd.  (hope hope)
So, if you have 0.1.3 running, there's nothing to change in the
kernel, and you just need to recompile pppd.


CONCLUSION

I'd appreciate hearing your experiences.  Does it work?  Does it drop
characters on machines less lame than mine (do you get ppp_toss
messages)?  What PPP servers do you use it with?  I'm eager for all
email on the subject.

Good luck!

Michael



----
Michael Callahan, Mathematical Institute, Oxford University
(home address: Holywell Manor, Manor Rd, Oxford OX1 3UH, England)
callahan@maths.ox.ac.uk
