Import Upstream version 2.4.7

This commit is contained in:
openKylinBot 2022-05-14 02:43:48 +08:00
commit 839cb1192c
234 changed files with 91294 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.orig
*~
*.o
*.so
*.a
*.cat8
Makefile

441
Changes-2.3 Normal file
View File

@ -0,0 +1,441 @@
What was new in ppp-2.3.11.
***************************
* Support for Solaris 8 has been added, including support for
replumbing and IPV6.
* The Solaris `snoop' utility should now work on ppp interfaces.
* New hooks have been added - pap_logout_hook, ip_up_hook, and
ip_down_hook.
* A new `passprompt' plugin is included, thanks to Alan Curry, which
makes it possible for pppd to call an external program to get the
PAP password to send to the peer.
* The error messages for the situation where authentication is
required because the system has a default route have been improved.
* There is a new connect_delay option which specifies how long pppd
should pause after the connect script finishes. Previously this
delay was fixed at 1 second. (This delay terminates as soon as pppd
sees a valid PPP frame from the peer.)
* The `hide-password' option is now the default, and there is a new
`show-password' option to enable the printing of password strings in
the debug output.
* A fairly complete list of the names of PPP protocols has been added
so that when pppd rejects a frame because its protocol is not
supported, it can print the name of the unsupported protocol.
* Synchronous serial lines are supported under Linux 2.3.x.
* The bug where pppd would not recognize a modem hangup under Linux
2.3.x kernels has been fixed.
What was new in ppp-2.3.10.
***************************
* Pppd now supports `plugins', which are pieces of code (packaged as
shared libraries) which can be loaded into pppd at runtime and which
can affect its behaviour. The intention is that plugins provide a
way for people to customize the behaviour of pppd for their own
needs without needing to change the base pppd source. I have added
some hooks into pppd (places where pppd will call a function
pointer, if non-zero, to replace some of pppd's code) and I will be
receptive to suggestions about places to add more hooks. Plugins
are supported under Linux and Solaris at present.
* We have a new maintainer for the Solaris port, Adi Masputra of Sun
Microsystems, and he has updated the Solaris port so that it should
work on 64-bit machines under Solaris 7 and later.
* Pppd now has an `allow-ip' option, which takes an argument which is
an IP address (or subnet) which peers are permitted to use without
authenticating themselves. The argument takes the same form as each
element of the allowed IP address list in the secrets files. The
allow-ip option is privileged and may be specified multiple times.
Using the allow-ip option should be cleaner than putting a line like
`"" * "" address' in /etc/ppp/pap-secrets.
* Chat can now substitute environment variables into the script. This
is enabled by the -E flag. (Thanks to Andreas Arens for the patch.)
* If the PAP username and password from the peer contains unprintable
characters, they will be translated to a printable form before
looking in the pap-secrets file. Characters >= 0x80 are translated
to a M- form, and characters from 0 to 0x1f (and 0x7f as well) are
translated to a ^X form. If this change causes you grief, let me
know what would be a better translation. It appears that some peers
send nulls or other control characters in their usernames and
passwords.
* Pppd has new `ktune' and `noktune' options, which enable/disable
it to change kernel settings as appropriate. This is only
implemented under Linux, and requires the /proc filesystem to be
mounted. Under Linux, with the ktune option, pppd will enable IP
forwarding in the kernel if the proxyarp option is used, and will
enable the dynamic IP address kernel option in demand mode if the
local IP address changes.
* Pppd no longer requires a remote address to be specified for demand
dialling. If none is specified, it will use a default value of
10.112.112.112+unit_number. (It will not propose this default to
the peer.)
* The default holdoff is now 0 if no connect script is given.
* The IPV6 code from Tommi Komulainen, which I unfortunately only
partially merged in to ppp-2.3.9, has been fixed and updated.
* The linux compilation glitches should be fixed now.
What was new in ppp-2.3.9.
**************************
* Support for the new generic PPP layer under development for the
Linux kernel.
* You can now place extra options to apply to specific users at the
end of the line with their password in the pap-secrets or
chap-secrets file, separated from the IP address(es) with a "--"
separator. These options are parsed after the peer is authenticated
but before network protocol (IPCP, IPXCP) or CCP negotiation
commences.
* Pppd will apply the holdoff period if the link was terminated by the
peer. It doesn't apply it if the link was terminated because the
local pppd thought it was idle.
* Synchronous support for Solaris has been added, thanks to John
Morrison, and for FreeBSD, thanks to Paul Fulghum.
* IPV6 support has been merged in, from Tommi Komulainen. At the
moment it only supports Linux and it is not tested by me.
* The `nodefaultip' option can be used in demand mode to say that pppd
should not suggest its local IP address to the peer.
* The `init' option has been added; this causes pppd to run a script
to initialize the serial device (e.g. by sending an init string to
the modem). Unlike the connect option, this can be used in a
dial-in situation. (Thanks to Tobias Ringstrom.)
* There is a new `logfile' option to send log messages to a file as
well as syslog.
* There is a new, privileged `linkname' option which sets a logical
name for the link. Pppd will create a /var/run/ppp-<linkname>.pid
file containing its process ID.
* There is a new `maxfail' option which specifies how many consecutive
failed connection attempts are permitted before pppd will exit. The
default value is 10, and 0 means infinity. :-)
* Sundry bugs fixed.
What was new in ppp-2.3.8.
**************************
* The exit status of pppd will now indicate whether the link was
successfully established, or if not, what error was encountered.
* Pppd has two new options: fdlog <n> will send log messages to file
descriptor <n> instead of standard output, and nofdlog will stop log
messages from being sent to any file descriptor (they will still be
sent to syslog). Pppd now will not send log messages to a file
descriptor if the serial port is open on that file descriptor.
* Pppd sets an environment variable called PPPLOGNAME for scripts that
it runs, indicating the login name of the user who invoked pppd.
* Pppd sets environment variables CONNECT_TIME, BYTES_SENT and
BYTES_RCVD for the ip-down and auth-down scripts indicating the
statistics for the connection just terminated. (CONNECT_TIME is in
seconds.)
* If the user has the serial device open on standard input and
specifies a symbolic link to the serial device on the command line,
pppd will detect this and behave correctly (i.e. not detach from its
controlling terminal). Furthermore, if the serial port is open for
reading and writing on standard input, pppd will assume that it is
locked by its invoker and not lock it itself.
* Chat now has a feature where if a string to be sent begins with an
at sign (@), the rest of the string is taken as the name of a file
(regular file or named pipe), and the actual string to send is taken
from that file.
* Support for FreeBSD-2.2.8 and 3.0 has been added, thanks to Paul
Fulghum.
* The Tru64 (aka Digital Unix aka OSF/1) port has been updated.
* The system panics on Solaris SMP systems related to PPP connections
being established and terminated should no longer occur.
* Fixed quite a few bugs.
What was new in ppp-2.3.7.
**************************
* Pppd can now automatically allocate itself a pseudo-tty to use as
the serial device. This has made three new options possible:
- `pty script' will run `script' with its standard input and output
connected to the master side of the pty. For example:
pppd pty 'ssh -t server.my.net pppd'
is a basic command for setting up a PPP link (tunnel) over ssh.
(In practice you may need to specify other options such as IP
addresses, etc.)
- `notty' tells pppd to communicate over its standard input and
output, which do not have to be a terminal device.
- `record filename' tells pppd to record all of the characters sent
and received over the serial device to a file called `filename'.
The data is recorded in a tagged format with timestamps, which can
be printed in a readable form with the pppdump program, which is
included in this distribution.
* Pppd now logs the connect time and number of bytes sent and received
(at the level of the serial device) when the connection is
terminated.
* If you use the updetach or nodetach option, pppd will print its
messages to standard output as well as logging them with syslog
(provided of course pppd isn't using its standard input or output as
its serial device).
* There is a new `privgroup groupname' option (a privileged option).
If the user running pppd is in group `groupname', s/he can use
privileged options without restriction.
* There is a new `receive-all' option, which causes pppd to accept all
control characters, even the ones that the peer should be escaping
(i.e. the receive asyncmap is 0). This is useful with some buggy
peers.
* The default asyncmap is now 0.
* There is a new `sync' option, currently only implemented under
Linux, which allows pppd to run on synchronous HDLC devices.
* If a value for the device name or for the connect, disconnect,
welcome or pty option is given in a privileged option file
(i.e. /etc/ppp/options or a file loaded with the `call' option), it
cannot be overridden by a non-privileged user.
* Many bugs have been fixed, notably:
- signals are not blocked unnecessarily, as they were in 2.3.6.
- the usepeerdns option should work now.
- the SPEED environment variable for scripts is set correctly.
- the /etc/ppp/auth-down script is not run until auth-up completes.
- the device is opened as root if it is the device on standard
input.
- pppd doesn't die with the ioctl(PPPIOCSASYNCMAP) error under linux
if a hangup occurs at the wrong time.
* Some error messages have been changed to be clearer (I hope :-)
What was new in ppp-2.3.6.
**************************
* Pppd now opens the tty device as the user (rather than as root) if
the device name was given by the user, i.e. on the command line or
in the ~/.ppprc file. If the device name was given in
/etc/ppp/options or in a file loaded with the `call' option, the
device is opened as root.
* The default behaviour of pppd is now to let a peer which has not
authenticated itself (e.g. your ISP) use any IP address to which the
system does not already have a route. (This is currently only
supported under Linux, Solaris and Digital Unix; on the other
systems, the peer must now authenticate itself unless the noauth
option is used.)
* Added new option `usepeerdns', thanks to Nick Walker
<nickwalker@email.com>. If the peer supplies DNS addresses, these
will be written to /etc/ppp/resolv.conf. The ip-up script can then
be used to add these addresses to /etc/resolv.conf if desired (see
the ip-up.local.add and ip-down.local.add files in the scripts
directory).
* The Solaris ppp driver should now work correctly on SMP systems.
* Minor corrections so that the code can compile under Solaris 7,
and under Linux with glibc-2.1.
* The Linux kernel driver has been restructured for improved
performance.
* Pppd now won't start the ip-down script until the ip-up script has
finished.
What was new in ppp-2.3.5.
**************************
* Minor corrections to the Digital UNIX and NetBSD ports.
* A workaround to avoid tickling a bug in the `se' serial port driver
on Sun PCI Ultra machines running Solaris.
* Fixed a bug in the negotiation of the Microsoft WINS server address
option.
* Fixed a bug in the Linux port where it would fail for kernel
versions above 2.1.99.
What was new in ppp-2.3.4.
**************************
* The NeXT port has been updated, thanks to Steve Perkins.
* ppp-2.3.4 compiles and works under Solaris 2.6, using either gcc or
cc.
* With the Solaris, SVR4 and SunOS ports, you can control the choice
of C compiler, C compiler options, and installation directories by
editing the svr4/Makedefs or sunos4/Makedefs file.
* Until now, we have been using the number 24 to identify Deflate
compression in the CCP negotiations, which was the number in the draft
RFC describing Deflate. The number actually assigned to Deflate is
26. The code has been changed to use 26, but to allow the use of 24
for now for backwards compatibility. (This can be disabled with the
`nodeflatedraft' option to pppd.)
* Fixed some bugs in the linux driver and deflate compressor which
were causing compression problems, including corrupting long
incompressible packets sometimes.
* Fixes to the PAM and shadow password support in pppd, from Al
Longyear and others.
* Pppd now sets some environment variables for scripts it invokes
(ip-up/down, auth-ip/down), giving information about the connection.
The variables it sets are PEERNAME, IPLOCAL, IPREMOTE, UID, DEVICE,
SPEED, and IFNAME.
* Pppd now has an `updetach' option, which will cause it to detach
from its controlling terminal once the link has come up (i.e. once it
is available for IP traffic).
What was new in ppp-2.3.3.
**************************
* Fixed compilation problems under SunOS.
* Fixed a bug introduced into chat in 2.3.2, and compilation problems
introduced into the MS-CHAP implementation in 2.3.2.
* The linux kernel driver has been updated for recent 2.1-series
kernel changes, and it now will ask kerneld to load compression
modules when required, if the kernel is configured to support kerneld.
* Pppd should now compile correctly under linux on systems with glibc.
What was new in ppp-2.3.2.
**************************
* In 2.3.1, I made a change which was intended to make pppd able to
detect loss of CD during or immediately after the connection script
runs. Unfortunately, this had the side-effect that the connection
script wouldn't work at all on some systems. This change has been
reversed.
* Fix compilation problems in the Linux kernel driver.
What was new in ppp-2.3.1.
**************************
* Enhancements to chat, thanks to Francis Demierre. Chat can now
accept comments in the chat script file, and has new SAY, HANGUP,
CLR_ABORT and CLR_REPORT keywords.
* Fixed a bug which causes 2.3.0 to crash Solaris systems.
* Bug-fixes and restructuring of the Linux kernel driver.
* The holdoff behaviour of pppd has been changed slightly: now, if
the link comes up for IP (or other network protocol) traffic, we
consider that the link has been successfully established, and don't
enforce the holdoff period after the link goes down.
* Pppd should now correctly wait for CD (carrier detect) from the
modem, even when the serial port initially had CLOCAL set, and it
should also detect loss of CD during or immediately after the
connection script runs.
* Under linux, pppd will work with older 2.2.0* version kernel
drivers, although demand-dialling is not supported with them.
* Minor bugfixes for pppd.
What was new in ppp-2.3.
************************
* Demand-dialling. Pppd now has a mode where it will establish the
network interface immediately when it starts, but not actually bring
the link up until it sees some data to be sent. Look for the demand
option description in the pppd man page. Demand-dialling is not
supported under Ultrix or NeXTStep.
* Idle timeout. Pppd will optionally terminate the link if no data
packets are sent or received within a certain time interval.
* Pppd now runs the /etc/ppp/auth-up script, if it exists, when the
peer successfully authenticates itself, and /etc/ppp/auth-down when
the connection is subsequently terminated. This can be useful for
accounting purposes.
* A new packet compression scheme, Deflate, has been implemented.
This uses the same compression method as `gzip'. This method is free
of patent or copyright restrictions, and it achieves better
compression than BSD-Compress. It does consume more CPU cycles for
compression than BSD-Compress, but this shouldn't be a problem for
links running at 100kbit/s or less.
* There is no code in this distribution which is covered by Brad
Clements' restrictive copyright notice. The STREAMS modules for SunOS
and OSF/1 have been rewritten, based on the Solaris 2 modules, which
were written from scratch without any Clements code.
* Pppstats has been reworked to clean up the output format somewhat.
It also has a new -d option which displays data rate in kbyte/s for
those columns which would normally display bytes.
* Pppd options beginning with - or + have been renamed, e.g. -ip
became noip, +chap became require-chap, etc. The old options are
still accepted for compatibility but may be removed in future.
* Pppd now has some options (such as the new `noauth' option) which
can only be specified if it is being run by root, or in an
"privileged" options file: /etc/ppp/options or an options file in the
/etc/ppp/peers directory. There is a new "call" option to read
options from a file in /etc/ppp/peers, making it possible for non-root
users to make unauthenticated connections, but only to certain trusted
peers. My intention is to make the `auth' option the default in a
future release.
* Several minor new features have been added to pppd, including the
maxconnect and welcome options. Pppd will now terminate the
connection when there are no network control protocols running. The
allowed IP address(es) field in the secrets files can now specify
subnets (with a notation like 123.45.67.89/24) and addresses which are
not acceptable (put a ! on the front).
* Numerous bugs have been fixed (no doubt some have been introduced :-)
Thanks to those who reported bugs in ppp-2.2.

636
FAQ Normal file
View File

@ -0,0 +1,636 @@
This is a list of Frequently Asked Questions about using ppp-2.x and
their answers.
------------------------------------------------------------------------
Q: Can you give me an example of how I might set up my machine to dial
out to an ISP?
A: Here's an example for dialling out to an ISP via a modem on
/dev/tty02. The modem uses hardware (CTS/RTS) flow control, and the
serial port is run at 38400 baud. The ISP assigns our IP address.
To configure pppd for this connection, create a file under
/etc/ppp/peers called (say) my-isp containing the following:
tty02 crtscts 38400
connect 'chat -v -f /etc/ppp/chat/my-isp'
defaultroute
The ppp connection is then initiated using the following command:
pppd call my-isp
Of course, if the directory containing pppd is not in your path, you
will need to give the full pathname for pppd, for example,
/usr/sbin/pppd.
When you run this, pppd will use the chat program to dial the ISP and
invoke its ppp service. Chat will read the file specified with -f,
namely /etc/ppp/chat/my-isp, to find a list of strings to expect to
receive, and strings to send. This file would contain something like
this:
ABORT "NO CARRIER"
ABORT "NO DIALTONE"
ABORT "ERROR"
ABORT "NO ANSWER"
ABORT "BUSY"
ABORT "Username/Password Incorrect"
"" "at"
OK "at&d2&c1"
OK "atdt2479381"
"name:" "^Uusername"
"word:" "\qpassword"
"annex" "\q^Uppp"
"Switching to PPP-ppp-Switching to PPP"
You will need to change the details here. The first string on each
line is a string to expect to receive; the second is the string to
send. You can add or delete lines according to the dialog required to
access your ISP's system. This example is for a modem with a standard
AT command set, dialling out to an Annex terminal server. The \q
toggles "quiet" mode; when quiet mode is on, the strings to be sent
are replaced by ?????? in the log. You may need to go through the
dialog manually using kermit or tip first to determine what should go
in the script.
To terminate the link, run the following script, called (say)
kill-ppp:
#!/bin/sh
unit=ppp${1-0}
piddir=/var/run
if [ -f $piddir/$unit.pid ]; then
kill -1 `cat $piddir/$unit.pid`
fi
On some systems (SunOS, Solaris, Ultrix), you will need to change
/var/run to /etc/ppp.
------------------------------------------------------------------------
Q: Can you give me an example of how I could set up my office machine
so I can dial in to it from home?
A: Let's assume that the office machine is called "office" and is on a
local ethernet subnet. Call the home machine "home" and give it an IP
address on the same subnet as "office". We'll require both machines
to authenticate themselves to each other.
Set up the files on "office" as follows:
/etc/ppp/options contains:
auth # require the peer to authenticate itself
lock
# other options can go here if desired
/etc/ppp/chap-secrets contains:
home office "beware the frub-jub" home
office home "bird, my son!%&*" -
Set up a modem on a serial port so that users can dial in to the
modem and get a login prompt.
On "home", set up the files as follows:
/etc/ppp/options contains the same as on "office".
/etc/ppp/chap-secrets contains:
home office "beware the frub-jub" -
office home "bird, my son!%&*" office
Create a file called /etc/ppp/peers/office containing the following:
tty02 crtscts 38400
connect 'chat -v -f /etc/ppp/chat/office'
defaultroute
(You may need to change some of the details here.)
Create the /etc/ppp/chat/office file containing the following:
ABORT "NO CARRIER"
ABORT "NO DIALTONE"
ABORT "ERROR"
ABORT "NO ANSWER"
ABORT "BUSY"
ABORT "ogin incorrect"
"" "at"
OK "at&d2&c1"
OK "atdt2479381"
"name:" "^Uusername"
"word:" "\qpassword"
"$" "\q^U/usr/sbin/pppd proxyarp"
"~"
You will need to change the details. Note that the "$" in the
second-last line is expecting the shell prompt after a successful
login - you may need to change it to "%" or something else.
You then initiate the connection (from home) with the command:
pppd call office
------------------------------------------------------------------------
Q: When I try to establish a connection, the modem successfully dials
the remote system, but then hangs up a few seconds later. How do I
find out what's going wrong?
A: There are a number of possible problems here. The first thing to
do is to ensure that pppd's messages are visible. Pppd uses the
syslog facility to log messages which help to identify specific
problems. Messages from pppd have facility "daemon" and levels
ranging from "debug" to "error".
Usually it is useful to see messages of level "notice" or higher on
the console. To see these, find the line in /etc/syslog.conf which
has /dev/console on the right-hand side, and add "daemon.notice" in
the list on the left. The line will end up looking something like
this:
*.err;kern.debug;auth.notice;mail.crit;daemon.notice /dev/console
Note that the whitespace is tabs, *not* spaces.
If you are having problems, it may be useful to see messages of level
"info" as well, in which case you would change "daemon.notice" to
"daemon.info".
In addition, it is useful to collect pppd's debugging output in a
file - the debug option to pppd causes it to log the contents of all
control packets sent and received in human-readable form. To do this,
add a line like this to /etc/syslog.conf:
daemon,local2.debug /etc/ppp/log
and create an empty /etc/ppp/log file.
When you change syslog.conf, you will need to send a HUP signal to
syslogd to causes it to re-read syslog.conf. You can do this with a
command like this (as root):
kill -HUP `cat /etc/syslogd.pid`
(On some systems, you need to use /var/run/syslog.pid instead of
/etc/syslogd.pid.)
After setting up syslog like this, you can use the -v flag to chat and
the `debug' option to pppd to get more information. Try initiating
the connection again; when it fails, inspect /etc/ppp/log to see what
happened and where the connection failed.
------------------------------------------------------------------------
Q: When I try to establish a connection, I get an error message saying
"Serial link is not 8-bit clean". Why?
A: The most common cause is that your connection script hasn't
successfully dialled out to the remote system and invoked ppp service
there. Instead, pppd is talking to something (a shell or login
process on the remote machine, or maybe just the modem) which is only
outputting 7-bit characters.
This can also arise with a modem which uses an AT command set if the
dial command is issued before pppd is invoked, rather than within a
connect script started by pppd. If the serial port is set to 7
bits/character plus parity when the last AT command is issued, the
modem serial port will be set to the same setting.
Note that pppd *always* sets the local serial port to 8 bits per
character, with no parity and 1 stop bit. So you shouldn't need to
issue an stty command before invoking pppd.
------------------------------------------------------------------------
Q: When I try to establish a connection, I get an error message saying
"Serial line is looped back". Why?
A: Probably your connection script hasn't successfully dialled out to
the remote system and invoked ppp service there. Instead, pppd is
talking to something which is just echoing back the characters it
receives. The -v option to chat can help you find out what's going
on. It can be useful to include "~" as the last expect string to
chat, so chat won't return until it's seen the start of the first PPP
frame from the remote system.
Another possibility is that your phone connection has dropped for some
obscure reason and the modem is echoing the characters it receives
from your system.
------------------------------------------------------------------------
Q: I installed pppd successfully, but when I try to run it, I get a
message saying something like "peer authentication required but no
authentication files accessible".
A: When pppd is used on a machine which already has a connection to
the Internet (or to be more precise, one which has a default route in
its routing table), it will require all peers to authenticate
themselves. The reason for this is that if you don't require
authentication, you have a security hole, because the peer can
basically choose any IP address it wants, even the IP address of some
trusted host (for example, a host mentioned in some .rhosts file).
On machines which don't have a default route, pppd does not require
the peer to authenticate itself. The reason is that such machines
would mostly be using pppd to dial out to an ISP which will refuse to
authenticate itself. In that case the peer can use any IP address as
long as the system does not already have a route to that address.
For example, if you have a local ethernet network, the peer can't use
an address on that network. (In fact it could if it authenticated
itself and it was permitted to use that address by the pap-secrets or
chap-secrets file.)
There are 3 ways around the problem:
1. If possible, arrange for the peer to authenticate itself, and
create the necessary secrets files (/etc/ppp/pap-secrets and/or
/etc/ppp/chap-secrets).
2. If the peer refuses to authenticate itself, and will always be
using the same IP address, or one of a small set of IP addresses, you
can create an entry in the /etc/ppp/pap-secrets file like this:
"" * "" his-ip.his-domain his-other-ip.other-domain
(that is, using the empty string for the client name and password
fields). Of couse, you replace the 4th and following fields in the
example above with the IP address(es) that the peer may use. You can
use either hostnames or numeric IP addresses.
3. You can add the `noauth' option to the /etc/ppp/options file.
Pppd will then not ask the peer to authenticate itself. If you do
this, I *strongly* recommend that you remove the set-uid bit from the
permissions on the pppd executable, with a command like this:
chmod u-s /usr/sbin/pppd
Then, an intruder could only use pppd maliciously if they had already
become root, in which case they couldn't do any more damage using pppd
than they could anyway.
------------------------------------------------------------------------
Q: What do I need to put in the secrets files?
A: Three things:
- secrets (i.e. passwords) to use for authenticating this host to
other hosts (i.e., for proving our identity to others);
- secrets which other hosts can use for authenticating themselves
to us (i.e., so that they can prove their identity to us); and
- information about which IP addresses other hosts may use, once
they have authenticated themselves.
There are two authentication files: /etc/ppp/pap-secrets, which
contains secrets for use with PAP (the Password Authentication
Protocol), and /etc/ppp/chap-secrets, which contains secrets for use
with CHAP (the Challenge Handshake Authentication Protocol). Both
files have the same simple format, which is as follows:
- The file contains a series of entries, each of which contains a
secret for authenticating one machine to another.
- Each entry is contained on a single logical line. A logical line
may be continued across several lines by placing a backslash (\) at
the end of each line except the last.
- Each entry has 3 or more fields, separated by whitespace (spaces
and/or tabs). These fields are, in order:
* The name of the machine that is authenticating itself
(the "client").
* The name of the machine that is authenticating the client
(the "server").
* The secret to be used for authenticating that client to that
server. If this field begins with the at-sign `@', the rest
of the field is taken as the name of a file containing the
actual secret.
* The 4th and any following fields list the IP address(es)
that the client may use.
- The file may contain comments, which begin with a `#' and continue
to the end of the line.
- Double quotes `"' should be used around a field if it contains
characters with special significance, such as space, tab, `#', etc.
- The backslash `\' may be used before characters with special
significance (space, tab, `#', `\', etc.) to remove that significance.
Some important points to note:
* A machine can be *both* a "client" and a "server" for the purposes
of authentication - this happens when both peers require the other to
authenticate itself. So A would authenticate itself to B, and B would
also authenticate itself to A (possibly using a different
authentication protocol).
* If both the "client" and the "server" are running ppp-2.x, they need
to have a similar entry in the appropriate secrets file; the first two
fields are *not* swapped on the client, compared to the server. So
the client might have an entry like this:
ay bee "our little secret" -
and the corresponding entry on the server could look like this:
ay bee "our little secret" 123.45.67.89
------------------------------------------------------------------------
Q: Explain about PAP and CHAP?
PAP stands for the Password Authentication Protocol. With this
protocol, the "client" (the machine that needs to authenticate itself)
sends its name and a password, in clear text, to the "server". The
server returns a message indicating whether the name and password are
valid.
CHAP stands for the Challenge Handshake Authentication Protocol. It
is designed to address some of the deficiencies and vulnerabilities of
PAP. Like PAP, it is based on the client and server having a shared
secret, but the secret is never passed in clear text over the link.
Instead, the server sends a "challenge" - an arbitrary string of
bytes, and the client must prove it knows the shared secret by
generating a hash value from the challenge combined with the shared
secret, and sending the hash value back to the server. The server
also generates the hash value and compares it with the value received
from the client.
At a practical level, CHAP can be slightly easier to configure than
PAP because the server sends its name with the challenge. Thus, when
finding the appropriate secret in the secrets file, the client knows
the server's name. In contrast, with PAP, the client has to find its
password (i.e. the shared secret) before it has received anything from
the server. Thus, it may be necessary to use the `remotename' option
to pppd when using PAP authentication so that it can select the
appropriate secret from /etc/ppp/pap-secrets.
Microsoft also has a variant of CHAP which uses a different hashing
arrangement from normal CHAP. There is a client-side (authenticatee)
implementation of Microsoft's CHAP in ppp-2.3; see README.MSCHAP80.
In ppp-2.4.2, server-side (authenticator) support was added as well as
support for Microsoft CHAP v2; see README.MSCHAP81.
------------------------------------------------------------------------
Q: When the modem hangs up, without the remote system having
terminated the connection properly, pppd does not notice the hangup,
but just keeps running. How do I get pppd to notice the hangup and
exit?
A: Pppd detects modem hangup by looking for an end-of-file indication
from the serial driver, which should be generated when the CD (carrier
detect) signal on the serial port is deasserted. For this to work:
- The modem has to be set to assert CD when the connection is made and
deassert it when the phone line hangs up. Usually the AT&C1 modem
command sets this mode.
- The cable from the modem to the serial port must connect the CD
signal (on pin 8).
- Some serial drivers have a "software carrier detect" mode, which
must be *disabled*. The method of doing this varies between systems.
Under SunOS, use the ttysoftcar command. Under NetBSD, edit /etc/ttys
to remove the "softcar" flag from the line for the serial port, and
run ttyflags.
------------------------------------------------------------------------
Q: Why should I use PPP compression (BSD-Compress or Deflate) when my
modem already does V.42 compression? Won't it slow the CPU down a
lot?
A: Using PPP compression is preferable, especially when using modems
over phone lines, for the following reasons:
- The V.42 compression in the modem isn't very strong - it's an LZW
technique (same as BSD-Compress) with a 10, 11 or 12 bit code size.
With BSD-Compress you can use a code size of up to 15 bits and get
much better compression, or you can use Deflate and get even better
compression ratios.
- I have found that enabling V.42 compression in my 14.4k modem
increases the round-trip time for a character to be sent, echoed and
returned by around 40ms, from 160ms to 200ms (with error correction
enabled). This is enough to make it feel less responsive on rlogin or
telnet sessions. Using PPP compression adds less than 5ms (small
enough that I couldn't measure it reliably). I admit my modem is a
cheapie and other modems may well perform better.
- While compression and decompression do require some CPU time, they
reduce the amount of time spent in the serial driver to transmit a
given amount of data. Many machines require an interrupt for each
character sent or received, and the interrupt handler can take a
significant amount of CPU time. So the increase in CPU load isn't as
great as you might think. My measurements indicate that a system with
a 33MHz 486 CPU should be able to do Deflate compression for serial
link speeds of up to 100kb/s or more. It depends somewhat on the type
of data, of course; for example, when compressing a string of nulls
with Deflate, it's hard to get a high output data rate from the
compressor, simply because it compresses strings of nulls so well that
it has to eat a very large amount of input data to get each byte of
output.
------------------------------------------------------------------------
Q: I get messages saying "Unsupported protocol (...) received". What do
these mean?
A: If you only get one or two when pppd starts negotiating with the
peer, they mean that the peer wanted to negotiate some PPP protocol
that pppd doesn't understand. This doesn't represent a problem, it
simply means that there is some functionality that the peer supports
that pppd doesn't, so that functionality can't be used.
If you get them sporadically while the link is operating, or if the
protocol numbers (in parentheses) don't correspond to any valid PPP
protocol that the peer might be using, then the problem is probably
that characters are getting corrupted on the receive side, or that
extra characters are being inserted into the receive stream somehow.
If this is happening, most packets that get corrupted should get
discarded by the FCS (Frame Check Sequence, a 16-bit CRC) check, but a
small number may get through.
One possibility may be that you are receiving broadcast messages on
the remote system which are being sent over your serial link. Another
possibility is that your modem is set for XON/XOFF (software) flow
control and is inserting ^Q and ^S characters into the receive data
stream.
------------------------------------------------------------------------
Q: I get messages saying "Protocol-Reject for unsupported protocol ...".
What do these mean?
A: This is the other side of the previous question. If characters are
getting corrupted on the way to the peer, or if your system is
inserting extra bogus characters into the transmit data stream, the
peer may send protocol-reject messages to you, resulting in the above
message (since your pppd doesn't recognize the protocol number
either.)
------------------------------------------------------------------------
Q: I get a message saying something like "ioctl(TIOCSETD): Operation
not permitted". How do I fix this?
A: This is because pppd is not running as root. If you have not
installed pppd setuid-root, you will have to be root to run it. If
you have installed pppd setuid-root and you still get this message, it
is probably because your shell is using some other copy of pppd than
the installed one - for example, if you are in the pppd directory
where you've just built pppd and your $PATH has . before /usr/sbin (or
wherever pppd gets installed).
------------------------------------------------------------------------
Q: Has your package been ported to HP/UX or IRIX or AIX?
A: No. I don't have access to systems running HP/UX or AIX. No-one
has volunteered to port it to HP/UX. I had someone who did a port for
AIX 4.x, but who is no longer able to maintain it. And apparently AIX
3.x is quite different, so it would need a separate port.
IRIX includes a good PPP implementation in the standard distribution,
as far as I know.
------------------------------------------------------------------------
Q: Under SunOS 4, when I try to modload the ppp modules, I get the
message "can't open /dev/vd: No such device".
A: First check in /dev that there is an entry like this:
crw-r--r-- 1 root 57, 0 Oct 2 1991 vd
If not, make one (mknod /dev/vd c 57 0). If the problem still exists,
probably your kernel has been configured without the vd driver
included. The vd driver is needed for loadable module support.
First, identify the config file that was used. When you boot your
machine, or if you run /etc/dmesg, you'll see a line that looks
something like this:
SunOS Release 4.1.3_U1 (CAP_XBOX) #7: Thu Mar 21 15:31:56 EST 1996
^^^^^^^^
this is the config file name
The config file will be in the /sys/`arch -k`/conf directory (arch -k
should return sun4m for a SparcStation 10, sun3x for a Sun 3/80,
etc.). Look in there for a line saying "options VDDRV". If that line
isn't present (or is commented out), add it (or uncomment it).
You then need to rebuild the kernel as described in the SunOS
manuals. Basically you need to run config and make like this:
/usr/etc/config CAP_XBOX
cd ../CAP_XBOX
make
(replacing the string CAP_XBOX by the name of the config file for your
kernel, of course).
Then copy the new kernel to /:
mv /vmunix /vmunix.working
cp vmunix /
and reboot. Modload should then work.
------------------------------------------------------------------------
Q: I'm running Linux (or NetBSD or FreeBSD), and my system comes with
PPP already. Should I consider installing this package? Why?
A: The PPP that is already installed in your system is (or is derived
from) some version of this PPP package. You can find out what version
of this package is already installed with the command "pppd --help".
If this is older than the latest version, you may wish to install the
latest version so that you can take advantage of the new features or
bug fixes.
------------------------------------------------------------------------
Q: I'm running pppd in demand mode, and I find that pppd often dials
out unnecessarily when I try to make a connection within my local
machine or with a machine on my local LAN. What can I do about this?
A: Very often the cause of this is that a program is trying to contact
a nameserver to resolve a hostname, and the nameserver (specified in
/etc/resolv.conf, usually) is on the far side of the ppp link. You
can try executing a command such as `ping myhost' (where myhost is the
name of the local machine, or some other machine on a local LAN), to
see whether that starts the ppp link. If it does, check the setup of
your /etc/hosts file to make sure you have the local machine and any
hosts on your local LAN listed, and /etc/resolv.conf and/or
/etc/nsswitch.conf files to make sure you resolve hostnames from
/etc/hosts if possible before trying to contact a nameserver.
------------------------------------------------------------------------
Q: Since I installed ppp-2.3.6, dialin users to my server have been
getting this message when they run pppd:
peer authentication required but no suitable secret(s) found for
authenticating any peer to us (ispserver)
A: In 2.3.6, the default is to let an unauthenticated peer only use IP
addresses to which the machine doesn't already have a route. So on a
machine with a default route, everyone has to authenticate. If you
really don't want that, you can put `noauth' in the /etc/ppp/options
file. Note that there is then no check on who is using which IP
address. IMHO, this is undesirably insecure, but I guess it may be
tolerable as long as you don't use any .rhosts files or anything like
that. I recommend that you require dialin users to authenticate, even
if just with PAP using their login password (using the `login' option
to pppd). If you do use `noauth', you should at least have a pppusers
group and set the permissions on pppd to allow only user and group to
execute it.
------------------------------------------------------------------------
Q: When running pppd as a dial-in server, I often get the message
"LCP: timeout sending Config-Requests" from pppd. It seems to be
random, but dial-out always works fine. What is wrong?
A: Most modern modems auto-detects the speed of the serial line
between the modem and the computer. This auto-detection occurs when
the computer sends characters to the modem, when the modem is in
command mode. It does not occur when the modem is in data mode.
Thus, if you send commands to the modem at 2400 bps, and then change
the serial port speed to 115200 bps, the modem will not detect this
change until something is transmitted from the computer to the modem.
When running pppd in dial-in mode (i.e. without a connect script),
pppd sets the speed of the serial port, but does not transmit
anything. If the modem was already running at the specified speed,
everything is fine, but if not, you will just receive garbage from the
modem. To cure this, use an init script such as the following:
pppd ttyS0 115200 modem crtscts init "chat '' AT OK"
To reset the modem and enable auto-answer, use:
pppd ttyS0 115200 modem crtscts init "chat '' ATZ OK ATS0=1 OK"

287
PLUGINS Normal file
View File

@ -0,0 +1,287 @@
Starting with version 2.3.10, pppd includes support for `plugins' -
pieces of code which can be loaded into pppd at runtime and which can
affect its behaviour in various ways. The idea of plugins is to
provide a way for people to customize the behaviour of pppd without
having to either apply local patches to each version or get their
patches accepted into the standard distribution.
A plugin is a standard shared library object, typically with a name
ending in .so. They are loaded using the standard dlopen() library
call, so plugins are only supported on systems which support shared
libraries and the dlopen call. At present pppd is compiled with
plugin support only under Linux and Solaris.
Plugins are loaded into pppd using the `plugin' option, which takes
one argument, the name of a shared object file. The plugin option is
a privileged option. If the name given does not contain a slash, pppd
will look in the /usr/lib/pppd/<version> directory for the file, where
<version> is the version number of pppd, for example, 2.4.2. I
suggest that you either give the full path name of the shared object
file or just the base name; if you don't, it may be possible for
unscrupulous users to substitute another shared object file for the
one you mean to load, e.g. by setting the LD_LIBRARY_PATH variable.
Plugins are usually written in C and compiled and linked to a shared
object file in the appropriate manner for your platform. Using gcc
under Linux, a plugin called `xyz' could be compiled and linked with
the following commands:
gcc -c -O xyz.c
gcc -shared -o xyz.so xyz.o
There are some example plugins in the pppd/plugins directory in the
ppp distribution. Currently there is one example, minconn.c, which
implements a `minconnect' option, which specifies a minimum connect
time before the idle timeout applies.
Plugins can access global variables within pppd, so it is useful for
them to #include "pppd.h" from the pppd source directory.
Every plugin must contain a global procedure called `plugin_init'.
This procedure will get called (with no arguments) immediately after
the plugin is loaded. Every plugin should also contain a variable
called pppd_version declared as follows:
char pppd_version[] = VERSION;
If this declaration is included, pppd will not load the module if its
version number differs from that compiled into the plugin binary.
Plugins can affect the behaviour of pppd in at least four ways:
1. They can add extra options which pppd will then recognize. This is
done by calling the add_options() procedure with a pointer to an
array of option_t structures. The last entry in the array must
have its name field set to NULL.
2. Pppd contains `hook' variables which are procedure pointers. If a
given hook is not NULL, pppd will call the procedure it points to
at the appropriate point in its processing. The plugin can set any
of these hooks to point to its own procedures. See below for a
description of the hooks which are currently implemented.
3. Plugin code can call any global procedures and access any global
variables in pppd.
4. Plugins can register procedures to be called when particular events
occur, using the `notifier' mechanism in pppd. The differences
between hooks and notifiers are that a hook will only call one
function, whereas a notifier can call an arbitrary number, and that
a hook usually returns some value to pppd, whereas a notifier
function returns nothing.
Here is a list of the currently implemented hooks in pppd.
int (*idle_time_hook)(struct ppp_idle *idlep);
The idle_time_hook is called when the link first comes up (i.e. when
the first network protocol comes up) and at intervals thereafter. On
the first call, the idlep parameter is NULL, and the return value is
the number of seconds before pppd should check the link activity, or 0
if there is to be no idle timeout.
On subsequent calls, idlep points to a structure giving the number of
seconds since the last packets were sent and received. If the return
value is > 0, pppd will wait that many seconds before checking again.
If it is <= 0, that indicates that the link should be terminated due
to lack of activity.
int (*holdoff_hook)(void);
The holdoff_hook is called when an attempt to bring up the link fails,
or the link is terminated, and the persist or demand option was used.
It returns the number of seconds that pppd should wait before trying
to reestablish the link (0 means immediately).
int (*pap_check_hook)(void);
int (*pap_passwd_hook)(char *user, char *passwd);
int (*pap_auth_hook)(char *user, char *passwd, char **msgp,
struct wordlist **paddrs,
struct wordlist **popts);
void (*pap_logout_hook)(void);
These hooks are designed to allow a plugin to replace the normal PAP
password processing in pppd with something different (e.g. contacting
an external server).
The pap_check_hook is called to check whether there is any possibility
that the peer could authenticate itself to us. If it returns 1, pppd
will ask the peer to authenticate itself. If it returns 0, pppd will
not ask the peer to authenticate itself (but if authentication is
required, pppd may exit, or terminate the link before network protocol
negotiation). If it returns -1, pppd will look in the pap-secrets
file as it would normally.
The pap_passwd_hook is called to determine what username and password
pppd should use in authenticating itself to the peer with PAP. The
user string will already be initialized, by the `user' option, the
`name' option, or from the hostname, but can be changed if necessary.
MAXNAMELEN bytes of space are available at *user, and MAXSECRETLEN
bytes of space at *passwd. If this hook returns 0, pppd will use the
values at *user and *passwd; if it returns -1, pppd will look in the
pap-secrets file, or use the value from the +ua or password option, as
it would normally.
The pap_auth_hook is called to determine whether the username and
password supplied by the peer are valid. user and passwd point to
null-terminated strings containing the username and password supplied
by the peer, with non-printable characters converted to a printable
form. The pap_auth_hook function should set msg to a string to be
returned to the peer and return 1 if the username/password was valid
and 0 if not. If the hook returns -1, pppd will look in the
pap-secrets file as usual.
If the username/password was valid, the hook can set *paddrs to point
to a wordlist containing the IP address(es) which the peer is
permitted to use, formatted as in the pap-secrets file. It can also
set *popts to a wordlist containing any extra options for this user
which pppd should apply at this point.
The pap_logout_hook is called when the link is terminated, instead of
pppd's internal `plogout' function. It can be used for accounting
purposes. This hook is deprecated and will be replaced by a notifier.
int (*chap_check_hook)(void);
int (*chap_passwd_hook)(char *user, char *passwd);
int (*chap_verify_hook)(char *name, char *ourname, int id,
struct chap_digest_type *digest,
unsigned char *challenge, unsigned char *response,
char *message, int message_space)
These hooks are designed to allow a plugin to replace the normal CHAP
password processing in pppd with something different (e.g. contacting
an external server).
The chap_check_hook is called to check whether there is any possibility
that the peer could authenticate itself to us. If it returns 1, pppd
will ask the peer to authenticate itself. If it returns 0, pppd will
not ask the peer to authenticate itself (but if authentication is
required, pppd may exit, or terminate the link before network protocol
negotiation). If it returns -1, pppd will look in the chap-secrets
file as it would normally.
The chap_passwd_hook is called to determine what password
pppd should use in authenticating itself to the peer with CHAP. The
user string will already be initialized, by the `user' option, the
`name' option, or from the hostname, but can be changed if necessary.
This hook is called only if pppd is a client, not if it is a server.
MAXSECRETLEN bytes of space are available at *passwd. If this hook
returns 0, pppd will use the value *passwd; if it returns -1, pppd
will fail to authenticate.
The chap_verify_hook is called to determine whether the peer's
response to our CHAP challenge is valid -- it should return 1 if valid
or 0 if not. The parameters are:
* name points to a null-terminated string containing the username
supplied by the peer, or the remote name specified with the
"remotename" option.
* ourname points to a null-terminated string containing the name of
the local machine (the hostname, or the name specified with the
"name" option).
* id is the value of the id field from the challenge.
* digest points to a chap_digest_type struct, which contains an
identifier for the type of digest in use plus function pointers for
functions for dealing with digests of that type.
* challenge points to the challenge as a counted string (length byte
followed by the actual challenge bytes).
* response points to the response as a counted string.
* message points to an area of message_space bytes in which to store
any message that should be returned to the peer.
int (*null_auth_hook)(struct wordlist **paddrs,
struct wordlist **popts);
This hook allows a plugin to determine what the policy should be if
the peer refuses to authenticate when it is requested to. If the
return value is 0, the link will be terminated; if it is 1, the
connection is allowed to proceed, and in this case *paddrs and *popts
can be set as for pap_auth_hook, to specify what IP addresses are
permitted and any extra options to be applied. If the return value is
-1, pppd will look in the pap-secrets file as usual.
void (*ip_choose_hook)(u_int32_t *addrp);
This hook is called at the beginning of IPCP negotiation. It gives a
plugin the opportunity to set the IP address for the peer; the address
should be stored in *addrp. If nothing is stored in *addrp, pppd will
determine the peer's address in the usual manner.
int (*allowed_address_hook)(u_int32_t addr)
This hook is called to see if a peer is allowed to use the specified
address. If the hook returns 1, the address is accepted. If it returns
0, the address is rejected. If it returns -1, the address is verified
in the normal away against the appropriate options and secrets files.
void (*snoop_recv_hook)(unsigned char *p, int len)
void (*snoop_send_hook)(unsigned char *p, int len)
These hooks are called whenever pppd receives or sends a packet. The
packet is in p; its length is len. This allows plugins to "snoop in"
on the pppd conversation. The hooks may prove useful in implmenting
L2TP.
void (*multilink_join_hook)();
This is called whenever a new link completes LCP negotiation and joins
the bundle, if we are doing multilink.
A plugin registers itself with a notifier by declaring a procedure of
the form:
void my_notify_proc(void *opaque, int arg);
and then registering the procedure with the appropriate notifier with
a call of the form
add_notifier(&interesting_notifier, my_notify_proc, opaque);
The `opaque' parameter in the add_notifier call will be passed to
my_notify_proc every time it is called. The `arg' parameter to
my_notify_proc depends on the notifier.
A notify procedure can be removed from the list for a notifier with a
call of the form
remove_notifier(&interesting_notifier, my_notify_proc, opaque);
Here is a list of the currently-implemented notifiers in pppd.
* pidchange. This notifier is called in the parent when pppd has
forked and the child is continuing pppd's processing, i.e. when pppd
detaches from its controlling terminal. The argument is the pid of
the child.
* phasechange. This is called when pppd moves from one phase of
operation to another. The argument is the new phase number.
* exitnotify. This is called just before pppd exits. The argument is
the status with which pppd will exit (i.e. the argument to exit()).
* sigreceived. This is called when a signal is received, from within
the signal handler. The argument is the signal number.
* ip_up_notifier. This is called when IPCP has come up.
* ip_down_notifier. This is called when IPCP goes down.
* auth_up_notifier. This is called when the peer has successfully
authenticated itself.
* link_down_notifier. This is called when the link goes down.
## $Id: PLUGINS,v 1.8 2008/06/15 07:02:18 paulus Exp $ ##

320
README Normal file
View File

@ -0,0 +1,320 @@
This is the README file for ppp-2.4, a package which implements the
Point-to-Point Protocol (PPP) to provide Internet connections over
serial lines.
Introduction.
*************
The Point-to-Point Protocol (PPP) provides a standard way to establish
a network connection over a serial link. At present, this package
supports IP and IPV6 and the protocols layered above them, such as TCP
and UDP. The Linux port of this package also has support for IPX.
This PPP implementation consists of two parts:
- Kernel code, which establishes a network interface and passes
packets between the serial port, the kernel networking code and the
PPP daemon (pppd). This code is implemented using STREAMS modules on
Solaris, and as a line discipline under Linux.
- The PPP daemon (pppd), which negotiates with the peer to establish
the link and sets up the ppp network interface. Pppd includes support
for authentication, so you can control which other systems may make a
PPP connection and what IP addresses they may use.
The platforms supported by this package are Linux and Solaris. I have
code for NeXTStep, FreeBSD, SunOS 4.x, SVR4, Tru64 (Digital Unix), AIX
and Ultrix but no active maintainers for these platforms. Code for
all of these except AIX is included in the ppp-2.3.11 release.
The kernel code for Linux is no longer distributed with this package,
since the relevant kernel code is in the official Linux kernel source
(and has been for many years) and is included in all reasonably modern
Linux distributions. The Linux kernel code supports using PPP over
things other than serial ports, such as PPP over Ethernet and PPP over
ATM.
Installation.
*************
The file SETUP contains general information about setting up your
system for using PPP. There is also a README file for each supported
system, which contains more specific details for installing PPP on
that system. The supported systems, and the corresponding README
files, are:
Linux README.linux
Solaris README.sol2
In each case you start by running the ./configure script. This works
out which operating system you are using and creates the appropriate
makefiles. You then run `make' to compile the user-level code, and
(as root) `make install' to install the user-level programs pppd, chat
and pppstats.
N.B. Since 2.3.0, leaving the permitted IP addresses column of the
pap-secrets or chap-secrets file empty means that no addresses are
permitted. You need to put a "*" in that column to allow the peer to
use any IP address. (This only applies where the peer is
authenticating itself to you, of course.)
What's new in ppp-2.4.7.
************************
* Fixed a potential security issue in parsing option files (CVE-2014-3158).
* There is a new "stop-bits" option, which takes an argument of 1 or 2,
indicating the number of stop bits to use for async serial ports.
* Various bug fixes.
What was new in ppp-2.4.6.
**************************
* Man page updates.
* Several bug fixes.
* Options files can now set and unset environment variables for
scripts.
* The timeout for chat scripts can now be taken from an environment
variable.
* There is a new option, master_detach, which allows pppd to detach
from the controlling terminal when it is the multilink bundle master
but its own link has terminated, even if the nodetach option has
been given.
What was new in ppp-2.4.5.
**************************
* Under Linux, pppd can now operate in a mode where it doesn't request
the peer's IP address, as some peers refuse to supply an IP address.
Since Linux supports device routes as well as gateway routes, it's
possible to have no remote IP address assigned to the ppp interface
and still route traffic over it.
* Pppd now works better with 3G modems that do strange things such as
sending IPCP Configure-Naks with the same values over and over again.
* The PPP over L2TP plugin is included, which works with the pppol2tp
PPP channel code in the Linux kernel. This allows pppd to be used
to set up tunnels using the Layer 2 Tunneling Protocol.
* A new 'enable-session' option has been added, which enables session
accounting via PAM or wtwp/wtmpx, as appropriate. See the pppd man
page for details.
* Several bugs have been fixed.
What was new in ppp-2.4.4.
**************************
* Pppd will now run /etc/ppp/ip-pre-up, if it exists, after creating
the ppp interface and configuring its IP addresses but before
bringing it up. This can be used, for example, for adding firewall
rules for the interface.
* Lots of bugs fixed, particularly in the area of demand-dialled and
persistent connections.
* The rp-pppoe plugin now accepts any interface name (that isn't an
existing pppd option name) without putting "nic-" on the front of
it, not just eth*, nas*, tap* and br*.
What was new in ppp-2.4.3.
**************************
* The configure script now accepts --prefix and --sysconfdir options.
These default to /usr/local and /etc. If you want pppd put in
/usr/sbin as before, use ./configure --prefix=/usr.
* Doing `make install' no longer puts example configuration files in
/etc/ppp. Use `make install-etcppp' if you want that.
* The code has been updated to work with version 0.8.3 of libpcap.
Unfortunately the libpcap maintainers removed support for the
"inbound" and "outbound" keywords on PPP links, meaning that if you
link pppd with libpcap-0.8.3, you can't use those keywords in the
active-filter and pass-filter expressions. The support has been
reinstated in the CVS version and should be in future libpcap
releases. If you need the in/outbound keywords, use a later release
than 0.8.3, or get the CVS version from http://www.tcpdump.org.
* There is a new option, child-timeout, which sets the length of time
that pppd will wait for child processes (such as the command
specified with the pty option) to exit before exiting itself. It
defaults to 5 seconds. After the timeout, pppd will send a SIGTERM
to any remaining child processes and exit. A value of 0 means no
timeout.
* Various bugs have been fixed, including some CBCP packet parsing
bugs that could lead to the peer being able to crash pppd if CBCP
support is enabled.
* Various fixes and enhancements to the radius and rp-pppoe plugins
have been added.
* There is a new winbind plugin, from Andrew Bartlet of the Samba
team, which provides the ability to authenticate the peer against an
NT domain controller using MS-CHAP or MS-CHAPV2.
* There is a new pppoatm plugin, by various authors, sent in by David
Woodhouse.
* The multilink code has been substantially reworked. The first pppd
for a bundle still controls the ppp interface, but it doesn't exit
until all the links in the bundle have terminated. If the first
pppd is signalled to exit, it signals all the other pppds
controlling links in the bundle.
* The TDB code has been updated to the latest version. This should
eliminate the problem that some people have seen where the database
file (/var/run/pppd.tdb) keeps on growing. Unfortunately, however,
the new code uses an incompatible database format. For this reason,
pppd now uses /var/run/pppd2.tdb as the database filename.
What was new in ppp-2.4.2.
**************************
* The CHAP code has been rewritten. Pppd now has support for MS-CHAP
V1 and V2 authentication, both as server and client. The new CHAP
code is cleaner than the old code and avoids some copyright problems
that existed in the old code.
* MPPE (Microsoft Point-to-Point Encryption) support has been added,
although the current implementation shouldn't be considered
completely secure. (There is no assurance that the current code
won't ever transmit an unencrypted packet.)
* James Carlson's implementation of the Extensible Authentication
Protocol (EAP) has been added.
* Support for the Encryption Control Protocol (ECP) has been added.
* Some new plug-ins have been included:
- A plug-in for kernel-mode PPPoE (PPP over Ethernet)
- A plug-in for supplying the PAP password over a pipe from another
process
- A plug-in for authenticating using a Radius server.
* Updates and bug-fixes for the Solaris port.
* The CBCP (Call Back Control Protocol) code has been updated. There
are new options `remotenumber' and `allow-number'.
* Extra hooks for plugins to use have been added.
* There is now a `maxoctets' option, which causes pppd to terminate
the link once the number of bytes passed on the link exceeds a given
value.
* There are now options to control whether pppd can use the IPCP
IP-Address and IP-Addresses options: `ipcp-no-address' and
`ipcp-no-addresses'.
* Fixed several bugs, including potential buffer overflows in chat.
What was new in ppp-2.4.1.
**************************
* Pppd can now print out the set of options that are in effect. The
new `dump' option causes pppd to print out the option values after
option parsing is complete. The `dryrun' option causes pppd to
print the options and then exit.
* The option parsing code has been fixed so that options in the
per-tty options file are parsed correctly, and don't override values
from the command line in most cases.
* The plugin option now looks in /usr/lib/pppd/<pppd-version> (for
example, /usr/lib/pppd/2.4.1b1) for shared objects for plugins if
there is no slash in the plugin name.
* When loading a plugin, pppd will now check the version of pppd for
which the plugin was compiled, and refuse to load it if it is
different to pppd's version string. To enable this, the plugin
source needs to #include "pppd.h" and have a line saying:
char pppd_version[] = VERSION;
* There is a bug in zlib, discovered by James Carlson, which can cause
kernel memory corruption if Deflate is used with the lowest setting,
8. As a workaround pppd will now insist on using at least 9.
* Pppd should compile on Solaris and SunOS again.
* Pppd should now set the MTU correctly on demand-dialled interfaces.
What was new in ppp-2.4.0.
**************************
* Multilink: this package now allows you to combine multiple serial
links into one logical link or `bundle', for increased bandwidth and
reduced latency. This is currently only supported under the
2.4.x and later Linux kernels.
* All the pppd processes running on a system now write information
into a common database. I used the `tdb' code from samba for this.
* New hooks have been added.
For a list of the changes made during the 2.3 series releases of this
package, see the Changes-2.3 file.
Compression methods.
********************
This package supports two packet compression methods: Deflate and
BSD-Compress. Other compression methods which are in common use
include Predictor, LZS, and MPPC. These methods are not supported for
two reasons - they are patent-encumbered, and they cause some packets
to expand slightly, which pppd doesn't currently allow for.
BSD-Compress and Deflate (which uses the same algorithm as gzip) don't
ever expand packets.
Contacts.
*********
The comp.protocols.ppp newsgroup is a useful place to get help if you
have trouble getting your ppp connections to work. Please do not send
me questions of the form "please help me get connected to my ISP" -
I'm sorry, but I simply do not have the time to answer all the
questions like this that I get.
If you find bugs in this package, please report them to the maintainer
for the port for the operating system you are using:
Linux Paul Mackerras <paulus@samba.org>
Solaris James Carlson <carlson@workingcode.com>
Copyrights:
***********
All of the code can be freely used and redistributed. The individual
source files each have their own copyright and permission notice.
Pppd, pppstats and pppdump are under BSD-style notices. Some of the
pppd plugins are GPL'd. Chat is public domain.
Distribution:
*************
The primary site for releases of this software is:
ftp://ftp.samba.org/pub/ppp/

78
README.MPPE Normal file
View File

@ -0,0 +1,78 @@
PPP Support for MPPE (Microsoft Point to Point Encryption)
==========================================================
Frank Cusack frank@google.com
Mar 19, 2002
Updated by Paul Mackerras, Sep 2008
DISCUSSION
MPPE is Microsoft's encryption scheme for PPP links. It is pretty much
solely intended for use with PPP over Internet links -- if you have a true
point to point link you have little need for encryption. It is generally
used with PPTP.
MPPE is negotiated within CCP (Compression Control Protocol) as option
18. In order for MPPE to work, both peers must agree to do it. This
complicates things enough that I chose to implement it as strictly a binary
option, off by default. If you turn it on, all other compression options
are disabled and MPPE *must* be negotiated successfully in both directions
(CCP is unidirectional) or the link will be disconnected. I think this is
reasonable since, if you want encryption, you want encryption. That is,
I am not convinced that optional encryption is useful.
While PPP regards MPPE as a "compressor", it actually expands every frame
by 4 bytes, the MPPE overhead (encapsulation).
Because of the data expansion, you'll see that ppp interfaces get their
mtu reduced by 4 bytes whenever MPPE is negotiated. This is because
when MPPE is active, it is *required* that *every* packet be encrypted.
PPPD sets the mtu = MIN(peer mru, configured mtu). To ensure that
MPPE frames are not larger than the peer's mru, we reduce the mtu by 4
bytes so that the network layer never sends ppp a packet that's too large.
There is an option to compress the data before encrypting (MPPC), however
the algorithm is patented and requires execution of a license with Hifn.
MPPC as an RFC is a complete farce. I have no further details on MPPC.
Some recommendations:
- Use stateless mode. Stateful mode is disabled by default. Unfortunately,
stateless mode is very expensive as the peers must rekey for every packet.
- Use 128-bit encryption.
- Use MS-CHAPv2 only.
Reference documents:
<http://www.ietf.org/rfc/rfc3078.txt> MPPE
<http://www.ietf.org/rfc/rfc3079.txt> MPPE Key Derivation
<http://www.ietf.org/rfc/rfc2118.txt> MPPC
<http://www.ietf.org/rfc/rfc2637.txt> PPTP
<http://www.ietf.org/rfc/rfc2548.txt> MS RADIUS Attributes
You might be interested in PoPToP, a Linux PPTP server. You can find it at
<http://www.poptop.org/>
RADIUS support for MPPE is from Ralf Hofmann, <ralf.hofmann@elvido.net>.
BUILDING THE PPPD
The userland component of PPPD has no additional requirements above
those for MS-CHAP and MS-CHAPv2.
MPPE support is now included in the mainline Linux kernel releases.
CONFIGURATION
See pppd(8) for the MPPE options. Under Linux, if your modutils is earlier
than 2.4.15, you will need to add
alias ppp-compress-18 ppp_mppe
to /etc/modules.conf.

151
README.MSCHAP80 Normal file
View File

@ -0,0 +1,151 @@
PPP Support for Microsoft's CHAP-80
===================================
Eric Rosenquist rosenqui@strataware.com
(updated by Paul Mackerras)
(updated by Al Longyear)
(updated by Farrell Woods)
(updated by Frank Cusack)
INTRODUCTION
Microsoft has introduced an extension to the Challenge/Handshake
Authentication Protocol (CHAP) which avoids storing cleartext
passwords on a server. (Unfortunately, this is not as secure as it
sounds, because the encrypted password stored on a server can be used
by a bogus client to gain access to the server just as easily as if
the password were stored in cleartext.) The details of the Microsoft
extensions can be found in the document:
<http://www.ietf.org/rfc/rfc2433.txt>
In short, MS-CHAP is identified as <auth chap 80> since the hex value
of 80 is used to designate Microsoft's scheme. Standard PPP CHAP uses
a value of 5. If you enable PPP debugging with the "debug" option and
see something like the following in your logs, the remote server is
requesting MS-CHAP:
rcvd [LCP ConfReq id=0x2 <asyncmap 0x0> <auth MS> <magic 0x46a3>]
^^^^^^^
MS-CHAP is enabled by default under Linux in pppd/Makefile.linux by
the line "CHAPMS=y".
CONFIGURATION
If you've never used PPPD with CHAP before, read the man page (type
"man pppd") and read the description in there. Basically, you need to
edit the "chap-secrets" file typically named /etc/ppp/chap-secrets.
This should contain the following two lines for each system with which
you use CHAP (with no leading blanks):
RemoteHost Account Secret
Account RemoteHost Secret
Note that you need both lines and that item 1 and 2 are swapped in the
second line. I'm not sure why you need it twice, but it works and I didn't
have time to look into it further. The "RemoteHost" is a somewhat
arbitrary name for the remote Windows NT system you're dialing. It doesn't
have to match the NT system's name, but it *does* have to match what you
use with the "remotename" parameter. The "Account" is the Windows NT
account name you have been told to use when dialing, and the "Secret" is
the password for that account. For example, if your service provider calls
their machine "DialupNT" and tells you your account and password are
"customer47" and "foobar", add the following to your chap-secrets file:
DialupNT customer47 foobar
customer47 DialupNT foobar
The only other thing you need to do for MS-CHAP (compared to normal CHAP)
is to always use the "remotename" option, either on the command line or in
your "options" file (see the pppd man page for details). In the case of
the above example, you would need to use the following command line:
pppd name customer47 remotename DialupNT <other options>
or add:
name customer47
remotename DialupNT
to your PPPD "options" file.
The "remotename" option is required for MS-CHAP since Microsoft PPP servers
don't send their system name in the CHAP challenge packet.
E=691 (AUTHENTICATION_FAILURE) ERRORS WHEN YOU HAVE THE VALID SECRET (PASSWORD)
If your RAS server is not the domain controller and is not a 'stand-alone'
server then it must make a query to the domain controller for your domain.
You need to specify the domain name with the user name when you attempt to
use this type of a configuration. The domain name is specified with the
local name in the chap-secrets file and with the option for the 'name'
parameter.
For example, the previous example would become:
DialupNT domain\\customer47 foobar
domain\\customer47 DialupNT foobar
and
pppd name 'domain\\customer47' remotename DialupNT <other options>
or add:
name domain\\customer47
remotename DialupNT
when the Windows NT domain name is simply called 'domain'.
TROUBLESHOOTING
Assuming that everything else has been configured correctly for PPP and
CHAP, the MS-CHAP-specific problems you're likely to encounter are mostly
related to your Windows NT account and its settings. A Microsoft server
returns error codes in its CHAP response. The following are extracted from
RFC 2433:
646 ERROR_RESTRICTED_LOGON_HOURS
647 ERROR_ACCT_DISABLED
648 ERROR_PASSWD_EXPIRED
649 ERROR_NO_DIALIN_PERMISSION
691 ERROR_AUTHENTICATION_FAILURE
709 ERROR_CHANGING_PASSWORD
You'll see these in your pppd log as a line similar to:
Remote message: E=649 R=0
The "E=" is the error number from the table above, and the "R=" flag
indicates whether the error is transient and the client should retry. If
you consistently get error 691, then either you're using the wrong account
name/password, or the DES library or MD4 hashing (in md4.c) aren't working
properly. Verify your account name and password (use a Windows NT or
Windows 95 system to dial-in if you have one available). If that checks
out, test the DES library with the "destest" program included with the DES
library. If DES checks out, the md4.c routines are probably failing
(system byte ordering may be a problem) or my code is screwing up. I've
only got access to a Linux system, so you're on your own for anything else.
Another thing that might cause problems is that some RAS servers won't
respond at all to LCP config requests without seeing the word "CLIENT"
from the other end. If you see pppd sending out LCP config requests
without getting any reply, try putting something in your chat script
to send the word CLIENT after the modem has connected.
STILL TO DO
A site using only MS-CHAP to authenticate has no need to store cleartext
passwords in the "chap-secrets" file. A utility that spits out the ASCII
hex MD4 hash of a given password would be nice, and would allow that hash
to be used in chap-secrets in place of the password. The code to do this
could quite easily be lifted from chap_ms.c (you have to convert the
password to Unicode before hashing it). The chap_ms.c file would also have
to be changed to recognize a password hash (16 binary bytes == 32 ASCII hex
characters) and skip the hashing stage. This would have no real security
value as the hash is plaintext-equivalent.

65
README.MSCHAP81 Normal file
View File

@ -0,0 +1,65 @@
PPP Support for Microsoft's CHAP-81
===================================
Frank Cusack frank@google.com
Some text verbatim from README.MSCHAP80,
by Eric Rosenquist, rosenqui@strataware.com
INTRODUCTION
First, please read README.MSCHAP80; almost everything there applies here.
MS-CHAP was basically devised by Microsoft because rather than store
plaintext passwords, they (Microsoft) store the md4 hash of passwords.
It provides no advantage over standard CHAP, since the hash is used
as plaintext-equivalent. (Well, the Change-Password packet is arguably
an advantage.) It does introduce a significant weakness if the LM hash
is used. Additionally, the format of the failure packet potentially
gives information to an attacker. The weakness of the LM hash is partly
addressed in RFC 2433, which deprecates its use.
MS-CHAPv2 adds 2 benefits to MS-CHAP. (1) The LM hash is no longer
used. (2) Mutual authentication is required. Note that the mutual
authentication in MS-CHAPv2 is different than the case where both PPP
peers require authentication from the other; the former proves that
the server has access to the client's password, the latter proves that
the server has access to a secret which the client also has -- which
may or may not be the same as the client's password (but should not be
the same, per RFC 1994). Whether this provides any actual benefit is
outside the scope of this document. The details of MS-CHAPv2 can be
found in the document:
<http://www.ietf.org/rfc/rfc2759.txt>
BUILDING THE PPPD
In addition to the requirements for MS-CHAP, MS-CHAPv2 uses the SHA-1
hash algorithm. A public domain implementation is provided with pppd.
TROUBLESHOOTING
Assuming that everything else has been configured correctly for PPP and
CHAP, the MS-CHAPv2-specific problems you're likely to encounter are mostly
related to your Windows NT account and its settings. A Microsoft server
returns error codes in its CHAP response. The following are extracted from
RFC 2759:
646 ERROR_RESTRICTED_LOGON_HOURS
647 ERROR_ACCT_DISABLED
648 ERROR_PASSWD_EXPIRED
649 ERROR_NO_DIALIN_PERMISSION
691 ERROR_AUTHENTICATION_FAILURE
709 ERROR_CHANGING_PASSWORD
You'll see these in your pppd log as a line similar to:
Remote message: E=649 No dialin permission
Previously, pppd would log this as:
Remote message: E=649 R=0
Now, the text message is logged (both for MS-CHAP and MS-CHAPv2).

51
README.cbcp Normal file
View File

@ -0,0 +1,51 @@
Microsoft Call Back Configuration Protocol.
by Pedro Roque Marques
(updated by Paul Mackerras)
The CBCP is a method by which the Microsoft Windows NT Server may
implement additional security. It is possible to configure the server
in such a manner so as to require that the client systems which
connect with it are required that following a valid authentication to
leave a method by which the number may be returned call.
It is a requirement of servers to be so configured that the protocol be
exchanged.
So, this set of patches may be applied to the pppd process to enable
the cbcp client *only* portion of the specification. It is primarily
meant to permit connection with Windows NT Servers.
The ietf-working specification may be obtained from ftp.microsoft.com
in the developr/rfc directory.
The ietf task group has decided to recommend that the LCP sequence be
extended to permit the callback operation. For this reason, these
patches are not 'part' of pppd but are an adjunct to the code.
To enable CBCP support, all that is required is to uncomment the line
in Makefile.linux that sets CBCP=y and recompile pppd.
I use such script to make a callback:
pppd debug nodetach /dev/modem 115200 crtscts modem \
callback 222222 name NAME remotename SERVER \
connect 'chat -v "" atz OK atdt111111 CONNECT ""'
sleep 1
pppd debug /dev/modem 115200 crtscts modem \
name NAME remotename SERVER defaultroute \
connect 'chat -v RING ATA CONNECT "\c"'
First we invoke pppd with 'nodetach' option in order to not detach from
the controlling terminal and 'callback NUMBER' option, then wait for
1 second and invoke pppd again which waits for a callback (RING) and
then answers (ATA). Number 222222 is a callback number, i.e. server will
call us back at this number, while number 111111 is the number we are
calling to.
You have to put in /etc/ppp/chap-secrets the following two lines:
NAME SERVER PASSWORD
SERVER NAME PASSWORD
You have to use your real login name, remote server name and password.

149
README.eap-srp Normal file
View File

@ -0,0 +1,149 @@
EAP with MD5-Challenge and SRP-SHA1 support
by James Carlson, Sun Microsystems
Version 2, September 22nd, 2002
1. What it does
The Extensible Authentication Protocol (EAP; RFC 2284) is a
security protocol that can be used with PPP. It provides a means
to plug in multiple optional authentication methods.
This implementation includes the required default MD5-Challenge
method, which is similar to CHAP (RFC 1994), as well as the new
SRP-SHA1 method. This latter method relies on an exchange that is
not vulnerable to dictionary attacks (as is CHAP), does not
require the server to keep a cleartext copy of the secret (as in
CHAP), supports identity privacy, and produces a temporary shared
key that could be used for data encryption.
The SRP-SHA1 method is based on draft-ietf-pppext-eap-srp-03.txt,
a work in progress.
2. Required libraries
Two other packages are required first. Download and install
OpenSSL and Thomas Wu's SRP implementation.
http://www.openssl.org/ (or ftp://ftp.openssl.org/source/)
http://srp.stanford.edu/
Follow the directions in each package to install the SSL and SRP
libraries. Once SRP is installed, you may run tconf as root to
create known fields, if desired. (This step is not required.)
3. Installing the patch
The EAP-SRP patch described here is integrated into this version
of pppd. The following patch may be used with older pppd sources:
ftp://playground.sun.com/carlsonj/eap/ppp-2.4.1-eap-1.tar.gz
Configure, compile, and install as root. You may want to edit
pppd/Makefile after configuring to enable or disable optional
features.
% ./configure
% make
% su
# make install
If you use csh or tcsh, run "rehash" to pick up the new commands.
If you're using Solaris, and you run into trouble with the
pseudonym feature on the server side ("no DES here" shows in the
log file), make sure that you have the "domestic" versions of the
DES libraries linked. You should see "crypt_d" in "ldd
/usr/local/bin/pppd". If you see "crypt_i" instead, then make
sure that /usr/lib/libcrypt.* links to /usr/lib/libcrypt_d.*. (If
you have the international version of Solaris, then you won't have
crypt_d. You might want to find an alternative DES library.)
4. Adding the secrets
On the EAP SRP-SHA1 client side, access to the cleartext secret is
required. This can be done in two ways:
- Enter the client name, server name, and password in the
/etc/ppp/srp-secrets file. This file has the same format as
the existing chap-secrets and pap-secrets files.
clientname servername "secret here"
- Use the "password" option in any of the standard
configuration files (or the command line) to specify the
secret.
password "secret here"
On the EAP SRP-SHA1 server side, a secret verifier is required.
This is a one-way hash of the client's name and password. To
generate this value, run the srp-entry program (see srp-entry(8)).
This program prompts for the client name and the passphrase (the
secret). The output will be an entry, such as the following,
suitable for use in the server's srp-secrets file. Note that if
this is transferred by cut-and-paste, the entry must be a single
line of text in the file.
pppuser srpserver 0:LFDpwg4HBLi4/kWByzbZpW6pE95/iIWBSt7L.DAkHsvwQphtiq0f6reoUy/1LC1qYqjcrV97lCDmQHQd4KIACGgtkhttLdP3KMowvS0wLXLo25FPJeG2sMAUEWu/HlJPn2/gHyh9aT.ZxUs5MsoQ1E61sJkVBc.2qze1CdZiQGTK3qtWRP6DOpM1bfhKtPoVm.g.MiCcTMWzc54xJUIA0mgKtpthE3JrqCc81cXUt4DYi5yBzeeGTqrI0z2/Gj8Jp7pS4Fkq3GmnYjMxnKfQorFXNwl3m7JSaPa8Gj9/BqnorJOsnSMlIhBe6dy4CYytuTbNb4Wv/nFkmSThK782V:2cIyMp1yKslQgE *
The "secret" field consists of three entries separated by colons.
The first entry is the index of the modulus and generator from
SRP's /etc/tpasswd.conf. If the special value 0 is used, then the
well-known modulus/generator value is used (this is recommended,
because it is much faster). The second value is the verifier
value. The third is the password "salt." These latter two values
are encoded in base64 notation.
For EAP MD5-Challenge, both client and server use the existing
/etc/ppp/chap-secrets file.
5. Configuration options
There are two main options relating to EAP available for the
client. These are:
refuse-eap - refuse to authenticate with EAP
srp-use-pseudonym - use the identity privacy if
offered by server
The second option stores a pseudonym, if offered by the EAP
SRP-SHA1 server, in the $HOME/.ppp_pseudonym file. The pseudonym
is typically an encrypted version of the client identity. During
EAP start-up, the pseudonym stored in this file is offered to the
peer as the identity. If this is accepted by the peer, then
eavesdroppers will be unable to determine the identity of the
client. Each time the client is authenticated, the server will
offer a new pseudoname to the client using an obscured (reversibly
encrypted) message. Thus, access across successive sessions
cannot be tracked.
There are two main options for EAP on the server:
require-eap - require client to use EAP
srp-pn-secret "string" - set server's pseudoname secret
The second option sets the long-term secret used on the server to
encrypt the user's identity to produce pseudonames. The
pseudoname is constructed by hashing this string with the current
date (to the nearest day) with SHA1, then using this hash as the
key for a DES encryption of the client's name. The date is added
to the hash for two reasons. First, this allows the pseudonym to
change daily. Second, it allows the server to decode any previous
pseudonym by trying previous dates.
See the pppd(8) man page for additional options.
6. Comments welcome!
This is still an experimental implementation. It has been tested
and reviewed carefully for correctness, but may still be
incomplete or have other flaws. All comments are welcome. Please
address them to the author:
james.d.carlson@sun.com
or, for EAP itself or the SRP extensions to EAP, to the IETF PPP
Extensions working group:
ietf-ppp@merit.edu

278
README.linux Normal file
View File

@ -0,0 +1,278 @@
PPP for Linux
-------------
Paul Mackerras
8 March 2001
for ppp-2.4.2
Updated for ppp-2.4.5, Sep 08
1. Introduction
---------------
The Linux PPP implementation includes both kernel and user-level
parts. This package contains the user-level part, which consists of
the PPP daemon (pppd) and associated utilities. In the past this
package has contained updated kernel drivers. This is no longer
necessary, as the current kernel sources contain up-to-date drivers
(and have done since the 2.4.x kernel series).
The Linux PPP implementation is capable of being used both for
initiating PPP connections (as a `client') or for handling incoming
PPP connections (as a `server'). Note that this is an operational
distinction, based on how the connection is created, rather than a
distinction that is made in the PPP protocols themselves.
Mostly this package is used for PPP connections over modems connected
via asynchronous serial ports, so this guide concentrates on this
situation.
The PPP protocol consists of two parts. One is a scheme for framing
and encoding packets, the other is a series of protocols called LCP,
IPCP, PAP and CHAP, for negotiating link options and for
authentication. This package similarly consists of two parts: a
kernel module 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.
2. Installation
---------------
2.1 Kernel driver
Assuming you are running a recent 2.4 or 2.6 (or later) series kernel,
the kernel source code will contain an up-to-date kernel PPP driver.
If the PPP driver was included in your kernel configuration when your
kernel was built, then you only need to install the user-level
programs. Otherwise you will need to get the source tree for your
kernel version, configure it with PPP included, and recompile. Most
Linux distribution vendors ship kernels with PPP included in the
configuration.
The PPP driver can be either compiled into the kernel or compiled as a
kernel module. If it is compiled into the kernel, the PPP driver is
included in the kernel image which is loaded at boot time. If it is
compiled as a module, the PPP driver is present in one or more files
under /lib/modules and is loaded into the kernel when needed.
The 2.2 series kernels contain an older version of the kernel PPP
driver, one which doesn't support multilink. If you want multilink,
you need to run a 2.4 or 2.6 series kernel. The kernel PPP driver
was completely rewritten for the 2.4 series kernels to support
multilink and to allow it to operate over diverse kinds of
communication medium (the 2.2 driver only operates over serial ports
and devices which look like serial ports, such as pseudo-ttys).
Under the 2.2 kernels, if PPP is compiled as a module, the PPP driver
modules should be present in the /lib/modules/`uname -r`/net directory
(where `uname -r` represents the kernel version number). The PPP
driver module itself is called ppp.o, and there will usually be
compression modules there, ppp_deflate.o and bsd_comp.o, as well as
slhc.o, which handles TCP/IP header compression. If the PPP driver is
compiled into the kernel, the compression code will still be compiled
as modules, for kernels before 2.2.17pre12. For 2.2.17pre12 and later,
if the PPP driver is compiled in, the compression code will also.
Under the 2.4 kernels, there are two PPP modules, ppp_generic.o and
ppp_async.o, plus the compression modules (ppp_deflate.o, bsd_comp.o
and slhc.o). If the PPP generic driver is compiled into the kernel,
the other four can then be present either as modules or compiled into
the kernel. There is a sixth module, ppp_synctty.o, which is used for
synchronous tty devices such as high-speed WAN adaptors.
2.2 User-level programs
If you obtained this package in .rpm or .deb format, you simply follow
the usual procedure for installing the package.
If you are using the .tar.gz form of this package, then cd into the
ppp-2.4.5 directory you obtained by unpacking the archive and issue
the following commands:
$ ./configure
$ make
# make install
The `make install' has to be done as root. This makes and installs
four programs and their man pages: pppd, chat, pppstats and pppdump.
If the /etc/ppp configuration directory doesn't exist, the `make
install' step will create it and install some default configuration
files.
2.3 System setup for 2.4 kernels
Under the 2.4 series kernels, pppd needs to be able to open /dev/ppp,
character device (108,0). If you are using udev (as most distributions
do), the /dev/ppp node should be created by udevd.
Otherwise you may need to create a /dev/ppp device node with the
commands:
# mknod /dev/ppp c 108 0
# chmod 600 /dev/ppp
2.4 System setup under 2.2 series kernels
Under the 2.2 series kernels, you should add the following to your
/etc/modules.conf or /etc/conf.modules:
alias tty-ldisc-3 ppp
alias ppp-compress-21 bsd_comp
alias ppp-compress-24 ppp_deflate
alias ppp-compress-26 ppp_deflate
3. Getting help with problems
-----------------------------
If you have problems with your PPP setup, or you just want to ask some
questions, or better yet if you can help others with their PPP
questions, then you should join the linux-ppp mailing list. Send an
email to majordomo@vger.kernel.org with a line in the body saying
subscribe linux-ppp
To leave the mailing list, send an email to majordomo@vger.kernel.org
with a line in the body saying
unsubscribe linux-ppp
To send a message to the list, email it to linux-ppp@vger.kernel.org.
You don't have to be subscribed to send messages to the list.
You can also email me (paulus@samba.org) but I am overloaded with
email and I can't respond to most messages I get in a timely fashion.
There are also several relevant news groups, such as comp.protocols.ppp,
comp.os.linux.networking, or comp.os.linux.setup.
4. Configuring your dial-out PPP connections
--------------------------------------------
Some Linux distribution makers include tools in their distributions
for setting up PPP connections. For example, for Red Hat Linux and
derivatives, you should probably use linuxconf or netcfg to set up
your PPP connections.
The two main windowing environments for Linux, KDE and Gnome, both
come with GUI utilities for configuring and controlling PPP dial-out
connections. They are convenient and relatively easy to configure.
A third alternative is to use a PPP front-end package such as wvdial
or ezppp. These also will handle most of the details of talking to
the modem and setting up the PPP connection for you.
Assuming that you don't want to use any of these tools, you want to
set up the configuration manually yourself, then read on. This
document gives a brief description and example. More details can be
found by reading the pppd and chat man pages and the PPP-HOWTO.
We assume that you have a modem that uses the Hayes-compatible AT
command set connected to an async serial port (e.g. /dev/ttyS0) and
that you are dialling out to an ISP.
The trickiest and most variable part of setting up a dial-out PPP
connection is the part which involves getting the modem to dial and
then invoking PPP service at the far end. Generally, once both ends
are talking PPP the rest is relatively straightforward.
Now in fact pppd doesn't know anything about how to get modems to dial
or what you have to say to the system at the far end to get it to talk
PPP. That's handled by an external program such as chat, specified
with the connect option to pppd. Chat takes a series of strings to
expect from the modem interleaved with a series of strings to send to
the modem. See the chat man page for more information. Here is a
simple example for connecting to an ISP, assuming that the ISP's
system starts talking PPP as soon as it answers the phone:
pppd connect 'chat -v "" AT OK ATDT5551212 ~' \
/dev/ttyS0 57600 crtscts debug defaultroute
Going through pppd's options in order:
connect 'chat ...' This gives a command to run to contact the
PPP server. Here the supplied 'chat' program is used to dial a
remote computer. The whole command is enclosed in single quotes
because pppd expects a one-word argument for the 'connect' option.
The options to 'chat' itself are:
-v verbose mode; log what we do to syslog
"" don't wait for any prompt, but instead...
AT send the string "AT"
OK expect the response "OK", then
ATDT5551212 dial the modem, then
~ wait for a ~ character, indicating the start
of a PPP frame from the server
/dev/ttyS0 specifies which serial port the modem is connected to
57600 specifies the baud rate to use
crtscts use hardware flow control using the RTS & CTS signals
debug log the PPP negotiation with syslog
defaultroute add default network route via the PPP link
Pppd will write error messages and debugging logs to the syslogd
daemon using the facility name "daemon". These messages may already
be logged to the console or to a file like /var/log/messages; consult
your /etc/syslog.conf file to see. If you want to make all pppd
messages go to a file such as /var/log/ppp-debug, add the line
daemon.* /var/log/ppp-debug
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is one or more tabs. Do not use spaces.
to syslog.conf; make sure to put one or more TAB characters (not
spaces!) between the two fields. Then you need to create an empty
/var/log/ppp-debug file with a command such as
touch /var/log/ppp-debug
and then restart syslogd, usually by sending it a SIGHUP signal with a
command like this:
killall -HUP syslogd
4.1 Is the link up?
The main way to tell if your PPP link is up and operational is the
ifconfig ("interface configuration") command. Type
/sbin/ifconfig
at a shell prompt. It should print a list of interfaces including one
like this example:
ppp0 Link encap Point-to-Point Protocol
inet addr 192.76.32.3 P-t-P 129.67.1.165 Mask 255.255.255.0
UP POINTOPOINT RUNNING MTU 1500 Metric 1
RX packets 33 errors 0 dropped 0 overrun 0
TX packets 42 errors 0 dropped 0 overrun 0
Assuming that ifconfig shows the ppp network interface, you can test
the link using the ping command like this:
/sbin/ping -c 3 129.67.1.165
where the address you give is the address shown as the P-t-P address
in the ifconfig output. If the link is operating correctly, you
should see output like this:
PING 129.67.1.165 (129.67.1.165): 56 data bytes
64 bytes from 129.67.1.165: icmp_seq=0 ttl=255 time=268 ms
64 bytes from 129.67.1.165: icmp_seq=1 ttl=255 time=247 ms
64 bytes from 129.67.1.165: icmp_seq=2 ttl=255 time=266 ms
--- 129.67.1.165 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 247/260/268 ms

93
README.pppoe Normal file
View File

@ -0,0 +1,93 @@
PPPoE Support
-------------
Michal Ostrowski
8 August 2001
for ppp-2.4.2
Updated for ppp-2.4.5 by Paul Mackerras, Sep 08
1. Introduction
---------------
This document describes the support for PPP over Ethernet (PPPoE)
included with this package. It is assumed that the reader is
familiar with Linux PPP (as it pertains to tty/modem-based
connections). In particular, users of PPP in the Linux 2.2 series
kernels should ensure they are familiar with the changes to the PPP
implementation in the 2.4 series kernels before attempting to use
PPPoE features.
If you are not familiar with PPP, I recommend looking at other
packages which include end-user configuration tools, such as Roaring
Penguin (http://www.roaringpenguin.com/pppoe).
PPPoE is a protocol typically used by *DSL providers to manage IP
addresses and authenticate users. Essentially, PPPoE provides for a
PPP connection to be established not over a physical serial-line or
modem, but over a logical connection between two unique MAC-addresses
on an ethernet network. Once the PPPoE layer discovers the end-points
to be used in the link and negotiates it, frames may be sent to and
received from the PPPoE layer just as if the link was a serial line
(or that is how it's supposed to be).
With this in mind, the goal of the implementation of PPPoE support in
Linux is to allow users to simply specify that the device they intend
to use for the PPP connection is an ethernet device (e.g. "eth0") and
the rest of the system should function as usual.
2. Using PPPoE
--------------
This section is a quick guide for getting PPPoE working, to allow one
to connect to their ISP who is providing PPPoE based services.
1. Enable "Prompt for development and/or incomplete code/drivers" and
"PPP over Ethernet" in your kernel configuration. Most distributions
will include the kernel PPPoE module by default.
2. Compile and install your kernel.
3. Install the ppp package.
4. Add the following line to /etc/ppp/options:
plugin rp-pppoe.so
The effect of this line is simply to make "eth0", "eth1",
....,"ethx" all valid device names for pppd (just like ttyS0,
ttyS1).
5. Add the necessary authentication options to your pppd
configuration (i.e. PAP/CHAP information). If you wish to
maintain seperate configurations for different devices you may
place configuration options in device-specific configuration
files: /etc/ppp/options.devname (devname=ttyS0, ttyS1, eth0, eth1
or any other valid device name).
6. Invoke pppd with the appropriate device name: e.g. "pppd eth0"
Do not include any compression or flow control options in your PPPoE
configuration. They will be ignored.
Again, here it is assumed that the reader is familiar with the general
process of configuring PPP. The steps outlined here refer only to the
steps and configuration options which are PPPoE specific, and it is
assumed that the reader will also configure other aspects of the system
(e.g. PAP authentication parameters).
3. Advanced Functionality
--------------------------
For more advanced functionality (such as providing PPPoE services) and
user configuration tools, look to the Roaring Penguin PPPoE software
package (http://www.roaringpenguin.com/pppoe).
4. Credits
-----------
The PPPoE plugin included in this package is a component of the
Roaring Penguin PPPoE package, included in this package courtesy of
Roaring Penguin Software. (http://www.roaringpenguin.com).

66
README.pppol2tp Normal file
View File

@ -0,0 +1,66 @@
PPPoL2TP plugin
===============
The pppol2tp plugin lets pppd use the Linux kernel driver pppol2tp.ko
to pass PPP frames in L2TP tunnels. The driver was integrated into the
kernel in the 2.6.23 release. For kernels before 2.6.23, an
out-of-tree kernel module is available from the pppol2tp-kmod package
in the OpenL2TP project.
Note that pppd receives only PPP control frames over the PPPoL2TP
socket; data frames are handled entirely by the kernel.
The pppol2tp plugin adds extra arguments to pppd and uses the Linux kernel
PPP-over-L2TP driver to set up each session's data path.
Arguments are:-
pppol2tp <fd> - FD for PPPoL2TP socket
pppol2tp_lns_mode - PPPoL2TP LNS behavior. Default off.
pppol2tp_send_seq - PPPoL2TP enable sequence numbers in
transmitted data packets. Default off.
pppol2tp_recv_seq - PPPoL2TP enforce sequence numbers in
received data packets. Default off.
pppol2tp_reorderto <millisecs> - PPPoL2TP data packet reorder timeout.
Default 0 (no reordering).
pppol2tp_debug_mask <mask> - PPPoL2TP debug mask. Bitwise OR of
1 - verbose debug
2 - control
4 - kernel transport
8 - ppp packet data
Default: 0 (no debug).
pppol2tp_ifname <ifname> - Name of PPP network interface visible
to "ifconfig" and "ip link".
Default: "pppN"
pppol2tp_tunnel_id <id> - L2TP tunnel_id tunneling this PPP
session.
pppol2tp_session_id <id> - L2TP session_id of this PPP session.
The tunnel_id/session_id pair is used
when sending event messages to openl2tpd.
pppd will typically be started by an L2TP daemon for each L2TP sesion,
supplying one or more of the above arguments as required. The pppd
user will usually have no visibility of these arguments.
Two hooks are exported by this plugin.
void (*pppol2tp_send_accm_hook)(int tunnel_id, int session_id,
uint32_t send_accm, uint32_t recv_accm);
void (*pppol2tp_ip_updown_hook)(int tunnel_id, int session_id, int up);
Credits
=======
This plugin was developed by Katalix Systems as part of the OpenL2TP
project, http://openl2tp.sourceforge.net. OpenL2TP is a full-featured
L2TP client-server, suitable for use as an enterprise L2TP VPN server
or a VPN client.
Please copy problems to the OpenL2TP mailing list:
openl2tp-users@lists.sourceforge.net.
Maintained by:
James Chapman
jchapman@katalix.com
Katalix Systems Ltd
http://www.katalix.com

174
README.pwfd Normal file
View File

@ -0,0 +1,174 @@
Support to pass the password via a pipe to the pppd
---------------------------------------------------
Arvin Schnell <arvin@suse.de>
2002-02-08
1. Introduction
---------------
Normally programs like wvdial or kppp read the online password from their
config file and store them in the pap- and chap-secrets before they start the
pppd and remove them afterwards. Sure they need special privileges to do so.
The passwordfd feature offers a simpler and more secure solution. The program
that starts the pppd opens a pipe and writes the password into it. The pppd
simply reads the password from that pipe.
This methods is used for quite a while on SuSE Linux by the programs wvdial,
kppp and smpppd.
2. Example
----------
Here is a short C program that uses the passwordfd feature. It starts the pppd
to buildup a pppoe connection.
--snip--
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <paths.h>
#ifndef _PATH_PPPD
#define _PATH_PPPD "/usr/sbin/pppd"
#endif
// Of course these values can be read from a configuration file or
// entered in a graphical dialog.
char *device = "eth0";
char *username = "1122334455661122334455660001@t-online.de";
char *password = "hello";
pid_t pid = 0;
void
sigproc (int src)
{
fprintf (stderr, "Sending signal %d to pid %d\n", src, pid);
kill (pid, src);
exit (EXIT_SUCCESS);
}
void
sigchild (int src)
{
fprintf (stderr, "Daemon died\n");
exit (EXIT_SUCCESS);
}
int
start_pppd ()
{
signal (SIGINT, &sigproc);
signal (SIGTERM, &sigproc);
signal (SIGCHLD, &sigchild);
pid = fork ();
if (pid < 0) {
fprintf (stderr, "unable to fork() for pppd: %m\n");
return 0;
}
if (pid == 0) {
int i, pppd_argc = 0;
char *pppd_argv[20];
char buffer[32] = "";
int pppd_passwdfd[2];
for (i = 0; i < 20; i++)
pppd_argv[i] = NULL;
pppd_argv[pppd_argc++] = "pppd";
pppd_argv[pppd_argc++] = "call";
pppd_argv[pppd_argc++] = "pwfd-test";
// The device must be after the call, since the call loads the plugin.
pppd_argv[pppd_argc++] = device;
pppd_argv[pppd_argc++] = "user";
pppd_argv[pppd_argc++] = username;
// Open a pipe to pass the password to pppd.
if (pipe (pppd_passwdfd) == -1) {
fprintf (stderr, "pipe failed: %m\n");
exit (EXIT_FAILURE);
}
// Of course this only works it the password is shorter
// than the pipe buffer. Otherwise you have to fork to
// prevent that your main program blocks.
write (pppd_passwdfd[1], password, strlen (password));
close (pppd_passwdfd[1]);
// Tell the pppd to read the password from the fd.
pppd_argv[pppd_argc++] = "passwordfd";
snprintf (buffer, 32, "%d", pppd_passwdfd[0]);
pppd_argv[pppd_argc++] = buffer;
if (execv (_PATH_PPPD, (char **) pppd_argv) < 0) {
fprintf (stderr, "cannot execl %s: %m\n", _PATH_PPPD);
exit (EXIT_FAILURE);
}
}
pause ();
return 1;
}
int
main (int argc, char **argv)
{
if (start_pppd ())
exit (EXIT_SUCCESS);
exit (EXIT_FAILURE);
}
---snip---
Copy this file to /etc/ppp/peers/pwfd-test. The plugins can't be loaded on the
command line (unless you are root) since the plugin option is privileged.
---snip---
#
# PPPoE plugin for kernel 2.4
#
plugin pppoe.so
#
# This plugin enables us to pipe the password to pppd, thus we don't have
# to fiddle with pap-secrets and chap-secrets. The user is also passed
# on the command line.
#
plugin passwordfd.so
noauth
usepeerdns
defaultroute
hide-password
nodetach
nopcomp
novjccomp
noccp
---snip---

260
README.sol2 Normal file
View File

@ -0,0 +1,260 @@
This file describes the installation process for ppp-2.4 on systems
running Solaris. The Solaris and SVR4 ports share a lot of code but
are not identical. The STREAMS kernel modules and driver for Solaris
are in the solaris directory (and use some code from the modules
directory).
NOTE: Although the kernel driver and modules have been designed to
operate correctly on SMP systems, they have not been extensively
tested on SMP machines. Some users of SMP Solaris x86 systems have
reported system problems apparently linked to the use of previous
versions of this software. I believe these problems have been fixed.
Installation.
*************
1. Run the configure script and make the user-level programs and the
kernel modules.
./configure
make
The configure script will automatically find Sun's cc if it's in
the standard location (/opt/SUNWspro/bin/cc). If you do not have
Sun's WorkShop compiler, configure will attempt to use 'gcc'. If
this is found and you have a 64 bit kernel, it will check that gcc
accepts the "-m64" option, which is required to build kernel
modules.
You should not have to edit the Makefiles for most ordinary cases.
2. Install the programs and kernel modules: as root, do
make install
This installs pppd, chat and pppstats in /usr/local/bin and the
kernel modules in /kernel/drv and /kernel/strmod, and creates the
/etc/ppp directory and populates it with default configuration
files. You can change the installation directories by editing
solaris/Makedefs. If you have a 64 bit kernel, the 64-bit drivers
are installed in /kernel/drv/sparcv9 and /kernel/strmod/sparcv9.
If your system normally has only one network interface at boot
time, the default Solaris system startup scripts will disable IP
forwarding in the IP kernel module. This will prevent the remote
machine from using the local machine as a gateway to access other
hosts. The solution is to create an /etc/ppp/ip-up script
containing something like this:
#!/bin/sh
/usr/sbin/ndd -set /dev/ip ip_forwarding 1
See the man page for ip(7p) for details.
Integrated pppd
***************
Solaris 8 07/01 (Update 5) and later have an integrated version of
pppd, known as "Solaris PPP 4.0," and is based on ppp-2.4.0. This
version comes with the standard Solaris software distribution and is
supported by Sun. It is fully tested in 64-bit and SMP modes, and
with bundled and unbundled synchronous drivers. Solaris 8 10/01
(Update 6) and later includes integrated PPPoE client and server
support, with kernel-resident data handling. See pppd(1M).
The feature is part of the regular full installation, and is
provided by these packages:
SUNWpppd - 32-bit mode kernel drivers
SUNWpppdr - root-resident /etc/ppp config samples
SUNWpppdu - /usr/bin/pppd itself, plus chat
SUNWpppdx - 64-bit mode kernel drivers
SUNWpppdt - PPPoE support
SUNWpppg - GPL'd optional 'pppdump' and plugins
SUNWpppgS - Source for GPL'd optional features
Use the open source version of pppd if you wish to recompile to add
new features or to experiment with the code. Production systems,
however, should run the Sun-supplied version, if at all possible.
You can run both versions on a single system if you wish. The
Solaris PPP 4.0 interfaces are named "spppN," while this open source
version names its interfaces as "pppN". The STREAMS modules are
similarly separated. The Sun-supplied pppd lives in /usr/bin/pppd,
while the open source version installs (by default) in
/usr/local/bin/pppd.
Dynamic STREAMS Re-Plumbing Support.
************************************
Solaris 8 (and later) includes dynamic re-plumbing support. With
this feature, modules below ip can be inserted, or removed, without
having the ip stream be unplumbed, and re-plumbed again. All state
in ip for the interface will be preserved as modules are added or
removed. Users can install (or upgrade) modules such as firewall,
bandwidth manager, cache manager, tunneling, etc., without shutting
the interface down.
To support this, ppp driver now uses /dev/udp instead of /dev/ip for
the ip stream. The interface stream (where ip module pushed on top
of ppp) is then I_PLINK'ed below the ip stream. /dev/udp is used
because STREAMS will not let a driver be PLINK'ed under itself, and
/dev/ip is typically the driver at the bottom of the tunneling
interfaces stream. The mux ids of the ip streams are then added
using SIOCSxIFMUXID ioctl.
Users will be able to see the modules on the interface stream by,
for example:
pikapon# ifconfig ppp modlist
0 ip
1 ppp
Or arbitrarily if bandwidth manager and firewall modules are installed:
pikapon# ifconfig hme0 modlist
0 arp
1 ip
2 ipqos
3 firewall
4 hme
Snoop Support.
**************
This version includes support for /usr/sbin/snoop. Tests have been
done on Solaris 7 through 9. Only IPv4 and IPv6 packets will be sent
up to stream(s) marked as promiscuous (i.e., those used by snoop).
Users will be able to see the packets on the ppp interface by, for
example:
snoop -d ppp0
See the man page for snoop(1M) for details.
IPv6 Support.
*************
This is for Solaris 8 and later.
This version has been tested under Solaris 8 and 9 running IPv6.
Interoperability testing has only been done between Solaris machines
in terms of the IPV6 NCP. An additional command line option for the
pppd daemon has been added: ipv6cp-use-persistent.
By default, compilation for IPv6 support is not enabled. Uncomment
the necessary lines in pppd/Makefile.sol2 to enable it. Once done,
the quickest way to get IPv6 running is to add the following
somewhere in the command line option:
+ipv6 ipv6cp-use-persistent
The persistent id for the link-local address was added to conform to
RFC 2472; such that if there's an EUI-48 available, use that to make
up the EUI-64. As of now, the Solaris implementation extracts the
EUI-48 id from the Ethernet's MAC address (the ethernet interface
needs to be up). Future work might support other ways of obtaining
a unique yet persistent id, such as EEPROM serial numbers, etc.
There need not be any up/down scripts for ipv6,
e.g. /etc/ppp/ipv6-up or /etc/ppp/ipv6-down, to trigger IPv6
neighbor discovery for auto configuration and routing. The in.ndpd
daemon will perform all of the necessary jobs in the
background. /etc/inet/ndpd.conf can be further customized to enable
the machine as an IPv6 router. See the man page for in.ndpd(1M) and
ndpd.conf(4) for details.
Below is a sample output of "ifconfig -a" with persistent link-local
address. Note the UNNUMBERED flag is set because hme0 and ppp0 both
have identical link-local IPv6 addresses:
lo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
hme0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
inet 129.146.86.248 netmask ffffff00 broadcast 129.146.86.255
ether 8:0:20:8d:38:c1
lo0: flags=2000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6> mtu 8252 index 1
inet6 ::1/128
hme0: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1500 index 2
ether 8:0:20:8d:38:c1
inet6 fe80::a00:20ff:fe8d:38c1/10
hme0:1: flags=2080841<UP,RUNNING,MULTICAST,ADDRCONF,IPv6> mtu 1500 index 2
inet6 fec0::56:a00:20ff:fe8d:38c1/64
hme0:2: flags=2080841<UP,RUNNING,MULTICAST,ADDRCONF,IPv6> mtu 1500 index 2
inet6 2000::56:a00:20ff:fe8d:38c1/64
hme0:3: flags=2080841<UP,RUNNING,MULTICAST,ADDRCONF,IPv6> mtu 1500 index 2
inet6 2::56:a00:20ff:fe8d:38c1/64
ppp0: flags=10008d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST,IPv4> mtu 1500 index 12
inet 172.16.1.1 --> 172.16.1.2 netmask ffffff00
ppp0: flags=2202851<UP,POINTOPOINT,RUNNING,MULTICAST,UNNUMBERED,NONUD,IPv6> mtu 1500 index 12
inet6 fe80::a00:20ff:fe8d:38c1/10 --> fe80::a00:20ff:fe7a:24fb
Note also that a plumbed ipv6 interface stream will exist throughout
the entire PPP session in the case where the peer rejects IPV6CP,
which further causes the interface state to stay down. Unplumbing
will happen when the daemon exits. This is done by design and is not
a bug.
64-bit Support.
***************
This version has been tested under Solaris 7 through 9 in both 32-
and 64-bit environments (Ultra class machines). Installing the
package by executing "make install" will result in additional files
residing in /kernel/drv/sparcv9 and /kernel/strmod/sparcv9
subdirectories.
64-bit modules and driver have been compiled and tested using Sun's
cc and gcc.
Synchronous Serial Support.
***************************
This version has working but limited support for the on-board
synchronous HDLC interfaces. It has been tested with the
/dev/se_hdlc, /dev/zsh, HSI/S, and HSI/P drivers. Synchronous mode
was tested with a Cisco router.
The ppp daemon does not directly support controlling the serial
interface. It relies on the /usr/sbin/syncinit command to
initialize HDLC mode and clocking.
There is a confirmed bug with NRZ/NRZI mode in the /dev/se_hdlc
driver, and Solaris patch 104596-11 is needed to correct it.
(However this patch seems to introduce other serial problems. If
you don't apply the patch, the workaround is to change the nrzi mode
to yes or no, whichever works.)
How to start pppd with synchronous support:
#!/bin/sh
local=1.1.1.1 # your ip address here
baud=38400 # needed, but ignored by serial driver
# Change to the correct serial driver/port
#dev=/dev/zsh0
dev=/dev/se_hdlc0
# Change the driver, nrzi mode, speed and clocking to match
# your setup.
# This configuration is for external clocking from the DCE
connect="syncinit se_hdlc0 nrzi=no speed=64000 txc=rxc rxc=rxc"
/usr/sbin/pppd $dev sync $baud novj noauth $local: connect "$connect"
Sample Cisco router config excerpt:
!
! Cisco router setup as DCE with RS-232 DCE cable
!
!
interface Serial0
ip address 1.1.1.2 255.255.255.0
encapsulation ppp
clockrate 64000
no nrzi-encoding
no shutdown
!

111
SETUP Normal file
View File

@ -0,0 +1,111 @@
Configuring a PPP link.
After you have compiled and installed this package, there are some
configuration files which will generally need to be set up. The
pppd(8) man page is the best reference for the full details; this file
outlines the configuration process for the most common case, where
this package is being used to enable a machine to dial an ISP and
connect to the internet. The FAQ and README.linux files also provide
useful information about setting up PPP.
Dialling an ISP.
****************
Usually, an ISP will assign an IP address to your machine, and will
refuse to authenticate itself to you. Some ISPs require a username
and password to be entered before PPP service commences, while others
use PPP authentication (using either the PAP or CHAP protocols).
The recommended way to set up to dial an ISP is for the system
administrator to create a file under /etc/ppp/peers, named for the ISP
that you will be dialling. For example, suppose the file is called
/etc/ppp/peers/isp. This file would contain something like this:
ttyS0 # modem is connected to /dev/ttyS0
38400 # run the serial port at 38400 baud
crtscts # use hardware flow control
noauth # don't require the ISP to authenticate itself
defaultroute # use the ISP as our default route
connect '/usr/sbin/chat -v -f /etc/ppp/chat-isp'
If there are any other pppd options that should apply when calling
this ISP, they can also be placed in this file.
The /etc/ppp/chat-isp file named in the last line contains the script
for chat(8) to use to dial the ISP and go through any username/
password authentication required before PPP service starts. Here is
an example (for dialling an Annex terminal server):
ABORT "NO CARRIER"
ABORT "NO DIALTONE"
ABORT "ERROR"
ABORT "NO ANSWER"
ABORT "BUSY"
ABORT "Username/Password Incorrect"
"" "at"
OK "at&d2&c1"
OK "atdt2479381"
"name:" "^Uusername"
"word:" "\qpassword"
"annex" "ppp"
"Switching to PPP-ppp-Switching to PPP"
See the chat(8) man page for details of the script. If you are not
sure how the initial dialog with your ISP will go, you could use
a terminal emulator such as kermit or minicom to go through the
process manually.
If your ISP requires PAP or CHAP authentication, you will have to
create a line in /etc/ppp/pap-secrets or /etc/ppp/chap-secrets like
this:
myhostname * "password"
(Replace myhostname with the hostname of your machine.)
At this point, you can initiate the link with the command:
/usr/sbin/pppd call isp
(N.B.: pppd might be installed in a different directory on some
systems).
This will return to the shell prompt immediately, as pppd will detach
itself from its controlling terminal. (If you don't want it to do
this, use the "nodetach" option.)
Pppd will log messages describing the progress of the connection and
any errors using the syslog facility (see the syslogd(8) and
syslog.conf(5) man pages). Pppd issues messages using syslog facility
daemon (or local2 if it has been compiled with debugging enabled);
chat uses facility local2. It is often useful to see messages of
priority notice or higher on the console. To see these, find the line
in /etc/syslog.conf which has /dev/console on the right-hand side, and
add `daemon.notice' on the left. This line should end up something
like this:
*.err;kern.debug;daemon,local2,auth.notice;mail.crit /dev/console
If you want to see more messages from pppd, request messages of
priority info or higher for facility daemon, like this:
*.err;kern.debug;daemon.info;local2,auth.notice;mail.crit /dev/console
It is also useful to add a line like this:
daemon,local2.debug /etc/ppp/ppp-log
If you do this, you will need to create an empty /etc/ppp/ppp-log
file.
After modifying syslog.conf, you will then need to send a HUP signal
to syslogd (or reboot).
When you wish terminate the PPP link, you should send a TERM or INTR
signal to pppd. Pppd writes its process ID to a file called
ppp<n>.pid in /var/run (or /etc/ppp on older systems such as SunOS or
Ultrix). Here <n> is the PPP interface unit number, which will be 0
unless you have more than one PPP link running simultaneously. Thus
you can terminate the link with a command like
kill `cat /var/run/ppp0.pid`

1
chat/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
chat

32
chat/Makefile.linux Normal file
View File

@ -0,0 +1,32 @@
# $Id: Makefile.linux,v 1.15 2006/06/04 05:07:46 paulus Exp $
DESTDIR = $(INSTROOT)@DESTDIR@
BINDIR = $(DESTDIR)/sbin
MANDIR = $(DESTDIR)/share/man/man8
CDEF1= -DTERMIOS # Use the termios structure
CDEF2= -DSIGTYPE=void # Standard definition
CDEF3= -UNO_SLEEP # Use the usleep function
CDEF4= -DFNDELAY=O_NDELAY # Old name value
CDEFS= $(CDEF1) $(CDEF2) $(CDEF3) $(CDEF4)
COPTS= -O2 -g -pipe
CFLAGS= $(COPTS) $(CDEFS)
INSTALL= install
all: chat
chat: chat.o
$(CC) -o chat chat.o
chat.o: chat.c
$(CC) -c $(CFLAGS) -o chat.o chat.c
install: chat
mkdir -p $(BINDIR) $(MANDIR)
$(INSTALL) -s -c chat $(BINDIR)
$(INSTALL) -c -m 644 chat.8 $(MANDIR)
clean:
rm -f chat.o chat *~

19
chat/Makefile.sol2 Normal file
View File

@ -0,0 +1,19 @@
#
# Makefile for chat on Solaris 2
#
include ../Makedefs.com
CFLAGS = $(COPTS) -DNO_USLEEP -DSOL2
all: chat
chat: chat.o
$(CC) -o chat chat.o
install: chat
$(INSTALL) -f $(BINDIR) chat
$(INSTALL) -m 444 -f $(MANDIR)/man8 chat.8
clean:
rm -f *~ *.o chat

514
chat/chat.8 Normal file
View File

@ -0,0 +1,514 @@
.\" -*- nroff -*-
.\" manual page [] for chat 1.8
.\" $Id: chat.8,v 1.11 2004/11/13 12:22:49 paulus Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
.\" IP indented paragraph
.\" TP hanging label
.TH CHAT 8 "22 May 1999" "Chat Version 1.22"
.SH NAME
chat \- Automated conversational script with a modem
.SH SYNOPSIS
.B chat
[
.I options
]
.I script
.SH DESCRIPTION
.LP
The \fIchat\fR program defines a conversational exchange between the
computer and the modem. Its primary purpose is to establish the
connection between the Point-to-Point Protocol Daemon (\fIpppd\fR) and
the remote's \fIpppd\fR process.
.SH OPTIONS
.TP
.B \-f \fI<chat file>
Read the chat script from the chat \fIfile\fR. The use of this option
is mutually exclusive with the chat script parameters. The user must
have read access to the file. Multiple lines are permitted in the
file. Space or horizontal tab characters should be used to separate
the strings.
.TP
.B \-t \fI<timeout>
Set the timeout for the expected string to be received. If the string
is not received within the time limit then the reply string is not
sent. An alternate reply may be sent or the script will fail if there
is no alternate reply string. A failed script will cause the
\fIchat\fR program to terminate with a non-zero error code.
.TP
.B \-r \fI<report file>
Set the file for output of the report strings. If you use the keyword
\fIREPORT\fR, the resulting strings are written to this file. If this
option is not used and you still use \fIREPORT\fR keywords, the
\fIstderr\fR file is used for the report strings.
.TP
.B \-e
Start with the echo option turned on. Echoing may also be turned on
or off at specific points in the chat script by using the \fIECHO\fR
keyword. When echoing is enabled, all output from the modem is echoed
to \fIstderr\fR.
.TP
.B \-E
Enables environment variable substitution within chat scripts using the
standard \fI$xxx\fR syntax.
.TP
.B \-v
Request that the \fIchat\fR script be executed in a verbose mode. The
\fIchat\fR program will then log the execution state of the chat
script as well as all text received from the modem and the output
strings sent to the modem. The default is to log through the SYSLOG;
the logging method may be altered with the \-S and \-s flags.
.TP
.B \-V
Request that the \fIchat\fR script be executed in a stderr verbose
mode. The \fIchat\fR program will then log all text received from the
modem and the output strings sent to the modem to the stderr device. This
device is usually the local console at the station running the chat or
pppd program.
.TP
.B \-s
Use stderr. All log messages from '\-v' and all error messages will be
sent to stderr.
.TP
.B \-S
Do not use the SYSLOG. By default, error messages are sent to the
SYSLOG. The use of \-S will prevent both log messages from '\-v' and
error messages from being sent to the SYSLOG.
.TP
.B \-T \fI<phone number>
Pass in an arbitrary string, usually a phone number, that will be
substituted for the \eT substitution metacharacter in a send string.
.TP
.B \-U \fI<phone number 2>
Pass in a second string, usually a phone number, that will be
substituted for the \eU substitution metacharacter in a send string.
This is useful when dialing an ISDN terminal adapter that requires two
numbers.
.TP
.B script
If the script is not specified in a file with the \fI\-f\fR option then
the script is included as parameters to the \fIchat\fR program.
.SH CHAT SCRIPT
.LP
The \fIchat\fR script defines the communications.
.LP
A script consists of one or more "expect\-send" pairs of strings,
separated by spaces, with an optional "subexpect\-subsend" string pair,
separated by a dash as in the following example:
.IP
ogin:\-BREAK\-ogin: ppp ssword: hello2u2
.LP
This line indicates that the \fIchat\fR program should expect the string
"ogin:". If it fails to receive a login prompt within the time interval
allotted, it is to send a break sequence to the remote and then expect the
string "ogin:". If the first "ogin:" is received then the break sequence is
not generated.
.LP
Once it received the login prompt the \fIchat\fR program will send the
string ppp and then expect the prompt "ssword:". When it receives the
prompt for the password, it will send the password hello2u2.
.LP
A carriage return is normally sent following the reply string. It is not
expected in the "expect" string unless it is specifically requested by using
the \er character sequence.
.LP
The expect sequence should contain only what is needed to identify the
string. Since it is normally stored on a disk file, it should not contain
variable information. It is generally not acceptable to look for time
strings, network identification strings, or other variable pieces of data as
an expect string.
.LP
To help correct for characters which may be corrupted during the initial
sequence, look for the string "ogin:" rather than "login:". It is possible
that the leading "l" character may be received in error and you may never
find the string even though it was sent by the system. For this reason,
scripts look for "ogin:" rather than "login:" and "ssword:" rather than
"password:".
.LP
A very simple script might look like this:
.IP
ogin: ppp ssword: hello2u2
.LP
In other words, expect ....ogin:, send ppp, expect ...ssword:, send hello2u2.
.LP
In actual practice, simple scripts are rare. At the vary least, you
should include sub-expect sequences should the original string not be
received. For example, consider the following script:
.IP
ogin:\-\-ogin: ppp ssword: hello2u2
.LP
This would be a better script than the simple one used earlier. This would look
for the same login: prompt, however, if one was not received, a single
return sequence is sent and then it will look for login: again. Should line
noise obscure the first login prompt then sending the empty line will
usually generate a login prompt again.
.SH COMMENTS
Comments can be embedded in the chat script. A comment is a line which
starts with the \fB#\fR (hash) character in column 1. Such comment
lines are just ignored by the chat program. If a '#' character is to
be expected as the first character of the expect sequence, you should
quote the expect string.
If you want to wait for a prompt that starts with a # (hash)
character, you would have to write something like this:
.IP
# Now wait for the prompt and send logout string
.br
\&'# ' logout
.LP
.SH SENDING DATA FROM A FILE
If the string to send starts with an at sign (@), the rest of the
string is taken to be the name of a file to read to get the string to
send. If the last character of the data read is a newline, it is
removed. The file can be a named pipe (or fifo) instead of a regular
file. This provides a way for \fBchat\fR to communicate with another
program, for example, a program to prompt the user and receive a
password typed in.
.LP
.SH ABORT STRINGS
Many modems will report the status of the call as a string. These
strings may be \fBCONNECTED\fR or \fBNO CARRIER\fR or \fBBUSY\fR. It
is often desirable to terminate the script should the modem fail to
connect to the remote. The difficulty is that a script would not know
exactly which modem string it may receive. On one attempt, it may
receive \fBBUSY\fR while the next time it may receive \fBNO CARRIER\fR.
.LP
These "abort" strings may be specified in the script using the \fIABORT\fR
sequence. It is written in the script as in the following example:
.IP
ABORT BUSY ABORT 'NO CARRIER' '' ATZ OK ATDT5551212 CONNECT
.LP
This sequence will expect nothing; and then send the string ATZ. The
expected response to this is the string \fIOK\fR. When it receives \fIOK\fR,
the string ATDT5551212 to dial the telephone. The expected string is
\fICONNECT\fR. If the string \fICONNECT\fR is received the remainder of the
script is executed. However, should the modem find a busy telephone, it will
send the string \fIBUSY\fR. This will cause the string to match the abort
character sequence. The script will then fail because it found a match to
the abort string. If it received the string \fINO CARRIER\fR, it will abort
for the same reason. Either string may be received. Either string will
terminate the \fIchat\fR script.
.SH CLR_ABORT STRINGS
This sequence allows for clearing previously set \fBABORT\fR strings.
\fBABORT\fR strings are kept in an array of a pre-determined size (at
compilation time); \fBCLR_ABORT\fR will reclaim the space for cleared
entries so that new strings can use that space.
.SH SAY STRINGS
The \fBSAY\fR directive allows the script to send strings to the user
at the terminal via standard error. If \fBchat\fR is being run by
pppd, and pppd is running as a daemon (detached from its controlling
terminal), standard error will normally be redirected to the file
/etc/ppp/connect\-errors.
.LP
\fBSAY\fR strings must be enclosed in single or double quotes. If
carriage return and line feed are needed in the string to be output,
you must explicitly add them to your string.
.LP
The SAY strings could be used to give progress messages in sections of
the script where you want to have 'ECHO OFF' but still let the user
know what is happening. An example is:
.IP
ABORT BUSY
.br
ECHO OFF
.br
SAY "Dialling your ISP...\en"
.br
\&'' ATDT5551212
.br
TIMEOUT 120
.br
SAY "Waiting up to 2 minutes for connection ... "
.br
CONNECT ''
.br
SAY "Connected, now logging in ...\en"
.br
ogin: account
.br
ssword: pass
.br
$ \ec
.br
SAY "Logged in OK ...\en"
\fIetc ...\fR
.LP
This sequence will only present the SAY strings to the user and all
the details of the script will remain hidden. For example, if the
above script works, the user will see:
.IP
Dialling your ISP...
.br
Waiting up to 2 minutes for connection ... Connected, now logging in ...
.br
Logged in OK ...
.LP
.SH REPORT STRINGS
A \fBreport\fR string is similar to the ABORT string. The difference
is that the strings, and all characters to the next control character
such as a carriage return, are written to the report file.
.LP
The report strings may be used to isolate the transmission rate of the
modem's connect string and return the value to the chat user. The
analysis of the report string logic occurs in conjunction with the
other string processing such as looking for the expect string. The use
of the same string for a report and abort sequence is probably not
very useful, however, it is possible.
.LP
The report strings to no change the completion code of the program.
.LP
These "report" strings may be specified in the script using the \fIREPORT\fR
sequence. It is written in the script as in the following example:
.IP
REPORT CONNECT ABORT BUSY '' ATDT5551212 CONNECT '' ogin: account
.LP
This sequence will expect nothing; and then send the string
ATDT5551212 to dial the telephone. The expected string is
\fICONNECT\fR. If the string \fICONNECT\fR is received the remainder
of the script is executed. In addition the program will write to the
expect\-file the string "CONNECT" plus any characters which follow it
such as the connection rate.
.SH CLR_REPORT STRINGS
This sequence allows for clearing previously set \fBREPORT\fR strings.
\fBREPORT\fR strings are kept in an array of a pre-determined size (at
compilation time); \fBCLR_REPORT\fR will reclaim the space for cleared
entries so that new strings can use that space.
.SH ECHO
The echo options controls whether the output from the modem is echoed
to \fIstderr\fR. This option may be set with the \fI\-e\fR option, but
it can also be controlled by the \fIECHO\fR keyword. The "expect\-send"
pair \fIECHO\fR \fION\fR enables echoing, and \fIECHO\fR \fIOFF\fR
disables it. With this keyword you can select which parts of the
conversation should be visible. For instance, with the following
script:
.IP
ABORT 'BUSY'
.br
ABORT 'NO CARRIER'
.br
\&'' ATZ
.br
OK\er\en ATD1234567
.br
\er\en \ec
.br
ECHO ON
.br
CONNECT \ec
.br
ogin: account
.LP
all output resulting from modem configuration and dialing is not visible,
but starting with the \fICONNECT\fR (or \fIBUSY\fR) message, everything
will be echoed.
.SH HANGUP
The HANGUP options control whether a modem hangup should be considered
as an error or not. This option is useful in scripts for dialling
systems which will hang up and call your system back. The HANGUP
options can be \fBON\fR or \fBOFF\fR.
.br
When HANGUP is set OFF and the modem hangs up (e.g., after the first
stage of logging in to a callback system), \fBchat\fR will continue
running the script (e.g., waiting for the incoming call and second
stage login prompt). As soon as the incoming call is connected, you
should use the \fBHANGUP ON\fR directive to reinstall normal hang up
signal behavior. Here is an (simple) example script:
.IP
ABORT 'BUSY'
.br
\&'' ATZ
.br
OK\er\en ATD1234567
.br
\er\en \ec
.br
CONNECT \ec
.br
\&'Callback login:' call_back_ID
.br
HANGUP OFF
.br
ABORT "Bad Login"
.br
\&'Callback Password:' Call_back_password
.br
TIMEOUT 120
.br
CONNECT \ec
.br
HANGUP ON
.br
ABORT "NO CARRIER"
.br
ogin:\-\-BREAK\-\-ogin: real_account
.br
\fIetc ...\fR
.LP
.SH TIMEOUT
The initial timeout value is 45 seconds. This may be changed using the \fB\-t\fR
parameter.
.LP
To change the timeout value for the next expect string, the following
example may be used:
.IP
ATZ OK ATDT5551212 CONNECT TIMEOUT 10 ogin:\-\-ogin: TIMEOUT 5 assword: hello2u2
.LP
This will change the timeout to 10 seconds when it expects the login:
prompt. The timeout is then changed to 5 seconds when it looks for the
password prompt.
.LP
The timeout, once changed, remains in effect until it is changed again.
.SH SENDING EOT
The special reply string of \fIEOT\fR indicates that the chat program
should send an EOT character to the remote. This is normally the
End-of-file character sequence. A return character is not sent
following the EOT.
The EOT sequence may be embedded into the send string using the
sequence \fI^D\fR.
.SH GENERATING BREAK
The special reply string of \fIBREAK\fR will cause a break condition
to be sent. The break is a special signal on the transmitter. The
normal processing on the receiver is to change the transmission rate.
It may be used to cycle through the available transmission rates on
the remote until you are able to receive a valid login prompt.
The break sequence may be embedded into the send string using the
\fI\eK\fR sequence.
.SH ESCAPE SEQUENCES
The expect and reply strings may contain escape sequences. All of the
sequences are legal in the reply string. Many are legal in the expect.
Those which are not valid in the expect sequence are so indicated.
.TP
.B ''
Expects or sends a null string. If you send a null string then it will still
send the return character. This sequence may either be a pair of apostrophe
or quote characters.
.TP
.B \eb
represents a backspace character.
.TP
.B \ec
Suppresses the newline at the end of the reply string. This is the only
method to send a string without a trailing return character. It must
be at the end of the send string. For example,
the sequence hello\ec will simply send the characters h, e, l, l, o.
.I (not valid in expect.)
.TP
.B \ed
Delay for one second. The program uses sleep(1) which will delay to a
maximum of one second.
.I (not valid in expect.)
.TP
.B \eK
Insert a BREAK
.I (not valid in expect.)
.TP
.B \en
Send a newline or linefeed character.
.TP
.B \eN
Send a null character. The same sequence may be represented by \e0.
.I (not valid in expect.)
.TP
.B \ep
Pause for a fraction of a second. The delay is 1/10th of a second.
.I (not valid in expect.)
.TP
.B \eq
Suppress writing the string to the SYSLOG file. The string ?????? is
written to the log in its place.
.I (not valid in expect.)
.TP
.B \er
Send or expect a carriage return.
.TP
.B \es
Represents a space character in the string. This may be used when it
is not desirable to quote the strings which contains spaces. The
sequence 'HI TIM' and HI\esTIM are the same.
.TP
.B \et
Send or expect a tab character.
.TP
.B \eT
Send the phone number string as specified with the \fI\-T\fR option
.I (not valid in expect.)
.TP
.B \eU
Send the phone number 2 string as specified with the \fI\-U\fR option
.I (not valid in expect.)
.TP
.B \e\e
Send or expect a backslash character.
.TP
.B \eddd
Collapse the octal digits (ddd) into a single ASCII character and send that
character.
.I (some characters are not valid in expect.)
.TP
.B \^^C
Substitute the sequence with the control character represented by C.
For example, the character DC1 (17) is shown as \^^Q.
.I (some characters are not valid in expect.)
.SH ENVIRONMENT VARIABLES
Environment variables are available within chat scripts, if the \fI\-E\fR
option was specified in the command line. The metacharacter \fI$\fR is used
to introduce the name of the environment variable to substitute. If the
substitution fails, because the requested environment variable is not set,
\fInothing\fR is replaced for the variable.
.SH TERMINATION CODES
The \fIchat\fR program will terminate with the following completion
codes.
.TP
.B 0
The normal termination of the program. This indicates that the script
was executed without error to the normal conclusion.
.TP
.B 1
One or more of the parameters are invalid or an expect string was too
large for the internal buffers. This indicates that the program as not
properly executed.
.TP
.B 2
An error occurred during the execution of the program. This may be due
to a read or write operation failing for some reason or chat receiving
a signal such as SIGINT.
.TP
.B 3
A timeout event occurred when there was an \fIexpect\fR string without
having a "\-subsend" string. This may mean that you did not program the
script correctly for the condition or that some unexpected event has
occurred and the expected string could not be found.
.TP
.B 4
The first string marked as an \fIABORT\fR condition occurred.
.TP
.B 5
The second string marked as an \fIABORT\fR condition occurred.
.TP
.B 6
The third string marked as an \fIABORT\fR condition occurred.
.TP
.B 7
The fourth string marked as an \fIABORT\fR condition occurred.
.TP
.B ...
The other termination codes are also strings marked as an \fIABORT\fR
condition.
.LP
Using the termination code, it is possible to determine which event
terminated the script. It is possible to decide if the string "BUSY"
was received from the modem as opposed to "NO DIAL TONE". While the
first event may be retried, the second will probably have little
chance of succeeding during a retry.
.SH SEE ALSO
Additional information about \fIchat\fR scripts may be found with UUCP
documentation. The \fIchat\fR script was taken from the ideas proposed
by the scripts used by the \fIuucico\fR program.
.LP
uucico(1), uucp(1)
.SH COPYRIGHT
The \fIchat\fR program is in public domain. This is not the GNU public
license. If it breaks then you get to keep both pieces.

1788
chat/chat.c Normal file

File diff suppressed because it is too large Load Diff

5379
common/zlib.c Normal file

File diff suppressed because it is too large Load Diff

1010
common/zlib.h Normal file

File diff suppressed because it is too large Load Diff

207
configure vendored Executable file
View File

@ -0,0 +1,207 @@
#!/bin/sh
# $Id: configure,v 1.38 2008/06/15 07:08:49 paulus Exp $
# Where to install stuff by default
DESTDIR=/usr/local
SYSCONF=/etc
# if [ -d /NextApps ]; then
# system="NeXTStep"
# else
system=`uname -s`
release=`uname -r`
arch=`uname -m`
# fi
state="unknown"
case $system in
Linux)
makext="linux";
ksrc="linux";
state="known";;
SunOS)
karch=`/usr/bin/isainfo -k`
case $release in
# [0-3]*) state="ancient";;
# 4*) state="known"; ksrc="sunos4"; makext="sunos4";;
5.[7-9]*|5.[1-9][0-9]*) state="known"; ksrc="solaris"; makext="sol2";
case "$karch" in
amd64) archvariant='-64x';;
sparcv9) archvariant='-64';;
*) ;;
esac;;
5.[1-6]*) state="known"; ksrc="solaris"; makext="sol2";;
esac
if [ "$1" = gcc ]; then
shift
usegcc=gcc
fi
if [ "$1" = 32 ]; then
shift
archvariant=
fi
if [ -x /opt/SUNWspro/bin/cc -a "$usegcc" != gcc ] &&
/opt/SUNWspro/bin/cc -flags >/dev/null 2>&1; then
if [ "$archvariant" = "-64x" ]; then
( cd /tmp; echo "int x;" > ppp$$.c
/opt/SUNWspro/bin/cc -c -errwarn -xchip=opteron -m64 ppp$$.c >/dev/null 2>&1 || (
echo "WorkShop C is unable to make 64 bit modules, and your $karch system needs"
echo "them. Consider upgrading cc on this machine."
rm -f ppp$$.c
exit 1
) || exit 1
rm -f ppp$$.c ppp$$.o
) || exit 1
fi
elif gcc --version >/dev/null 2>&1; then
archvariant=gcc$archvariant
compiletype=.gcc
if [ "$archvariant" = "gcc-64" -o"$archvariant" = "gcc-64x" ]; then
( cd /tmp; touch ppp$$.c
gcc -c -m64 ppp$$.c >/dev/null 2>&1 || (
echo "gcc is unable to make 64 bit modules, and your $karch system needs them."
echo "Consider upgrading gcc on this machine, or switching to Sun WorkShop."
rm -f ppp$$.c
exit 1
) || exit 1
rm -f ppp$$.c ppp$$.o
) || exit 1
fi
else
echo "C compiler not found; hoping for the best."
fi;;
NetBSD|FreeBSD|ULTRIX|OSF1|NeXTStep|SINIX-?|UNIX_SV|UNIX_System_V)
state="notincluded";;
# NetBSD)
# makext="bsd";
# case $release in
# 0.*) state="ancient";;
# 1.0*) state="ancient";;
# 1.1*) state="known"; ksrc="netbsd-1.1";;
# 1.2*) state="known"; ksrc="netbsd-1.2"; makext="netbsd-1.2";;
# 1.[3-9]*|[2-9]*)
# state="late"; ksrc="netbsd-1.2";;
# esac;;
# ULTRIX)
# makext="ultrix";
# case $release in
# [0-3]*) state="ancient";;
# 4.[01]*) state="early"; ksrc="ultrix";;
# 4.[234]) state="known"; ksrc="ultrix";;
# esac;;
# OSF1)
# makext="osf";
# case $release in
# V1.*) state="neolithic"; ksrc="osf1";;
# V[23].*) state="neolithic"; ksrc="osf1";;
# V4.*) state="known"; ksrc="osf1";;
# V[5-9]*) state="late"; ksrc="osf1";;
# esac;;
# FreeBSD)
# makext="bsd";
# case $release in
# 1.*) state="known"; ksrc="freebsd-old";;
# 2.[01]*) state="known"; ksrc="freebsd-2.0";;
# 2.2.[2-7]*) state="late"; ksrc="freebsd-2.0";;
# 2.2.8*) state="known"; ksrc="freebsd-2.2.8";;
# 3.[0-1]*) state="known"; ksrc="freebsd-3.0";;
# esac;;
# NeXTStep)
# makext="NeXT";
# ksrc="NeXT";
# state="known";;
# SINIX-?)
# case $release in
# 5.4[01]) state=known; ksrc=svr4; makext=svr4;;
# 5.4[2-9]) state=late; ksrc=svr4; makext=svr4;;
# esac;;
# # Intel SVR4 systems come with a bug in the uname program. Unless
# # your provider fixed the bug, or you get a fix for it, uname -S will
# # overwrite the system name with the node name!
# UNIX_SV|UNIX_System_V|`uname -n`)
# case $release in
# 4.0) state=known; ksrc=svr4; makext=svr4;;
# 4.2) state=late; ksrc=svr4; makext=svr4;;
# esac;;
esac
if [ -d "$ksrc" ]; then :; else
state="notincluded"
unset ksrc
fi
case $state in
neolithic)
echo "This is a newer release on an outdated OS ($system)."
echo " This software may or may not work on this OS."
echo " You may want to download an older version of PPP for this OS.";;
ancient)
echo "This is an old release of a supported OS ($system)."
echo "This software cannot be used as-is on this system,"
echo "but you may be able to port it. Good luck!"
exit;;
early)
echo "This is an old release of a supported OS ($system)."
echo "This software should install and run on this system,"
echo "but it hasn't been tested.";;
late)
echo "This is a newer release of $system than is supported by"
echo "this software. It may or may not work.";;
unknown)
echo "This software has not been ported to $system. Sorry.";;
notincluded)
echo "Support for $system has not been included"
echo "in this distribution. Sorry.";;
known)
echo "Configuring for $system";;
esac
# Parse arguments
while [ $# -gt 0 ]; do
arg=$1
val=
shift
case $arg in
*=*)
val=`expr "x$arg" : 'x[^=]*=\(.*\)'`
arg=`expr "x$arg" : 'x\([^=]*\)=.*'`
;;
--prefix|--sysconf)
if [ $# -eq 0 ]; then
echo "error: the $arg argument requires a value" 1>&2
exit 1
fi
val=$1
shift
;;
esac
case $arg in
--prefix) DESTDIR=$val ;;
--sysconfdir) SYSCONF=$val ;;
esac
done
mkmkf() {
rm -f $2
if [ -f $1 ]; then
echo " $2 <= $1"
sed -e "s,@DESTDIR@,$DESTDIR,g" -e "s,@SYSCONF@,$SYSCONF,g" $1 >$2
fi
}
if [ -d "$ksrc" ]; then
echo "Creating Makefiles."
mkmkf $ksrc/Makefile.top Makefile
mkmkf $ksrc/Makedefs$compiletype Makedefs.com
for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/rp-pppoe \
pppd/plugins/radius pppd/plugins/pppoatm \
pppd/plugins/pppol2tp; do
mkmkf $dir/Makefile.$makext $dir/Makefile
done
if [ -f $ksrc/Makefile.$makext$archvariant ]; then
mkmkf $ksrc/Makefile.$makext$archvariant $ksrc/Makefile
fi
else
echo "Unable to locate kernel source $ksrc"
exit 1
fi

View File

@ -0,0 +1,16 @@
all: pppgetpass.vt pppgetpass.gtk
pppgetpass.vt: pppgetpass.vt.o
pppgetpass.gtk: pppgetpass.gtk.o
$(CC) $(LDFLAGS) pppgetpass.gtk.o -o pppgetpass.gtk `pkg-config --libs glib-2.0 gtk+-2.0`
pppgetpass.gtk.o: pppgetpass.gtk.c
$(CC) $(CFLAGS) -c pppgetpass.gtk.c `pkg-config --cflags glib-2.0 gtk+-2.0`
install: all
install -m 755 pppgetpass.sh /usr/bin/pppgetpass
install -m 4755 -o root -g root pppgetpass.vt /usr/bin/
install -m 755 -o root -g root pppgetpass.gtk /usr/X11/bin/
clean:
rm -f *.o pppgetpass.gtk pppgetpass.vt core

View File

@ -0,0 +1,18 @@
.TH PPPGETPASS 8 "26 Sep 1999"
.SH NAME
pppgetpass \- prompt for PAP password
.SH SYNOPSIS
.B pppgetpass
.I client server fd
.SH DESCRIPTION
.B pppgetpass
the outer half of a plugin for PAP password prompting in pppd.
If the peer requires PAP, and the
.B passprompt.so
plugin is loaded into pppd, it will run
.B /usr/sbin/pppgetpass
(or another program specified by the
.B promptprog
option) to prompt the user for the password.
.SH SEE ALSO
pppd(8)

View File

@ -0,0 +1,92 @@
#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtkwindow.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkentry.h>
#include <gtk/gtksignal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
int outfd;
int err;
static void okpressed(void *widget, void *clientdata)
{
GtkWidget *answer=clientdata;
gchar *pass;
int passlen;
ssize_t wrote;
(void)widget;
pass=gtk_entry_get_text(GTK_ENTRY(answer));
passlen=strlen(pass);
if(!passlen)
return;
if((wrote=write(outfd, pass, passlen))!=passlen) {
if(wrote<0)
syslog(LOG_ERR, "write error on outpipe: %m");
else
syslog(LOG_ERR, "short write on outpipe");
err=1;
}
gtk_main_quit();
}
int main(int argc, char **argv)
{
GtkWidget *mainwindow, *vbox, *question, *answer, *ok;
char buf[1024];
gtk_init(&argc, &argv);
openlog(argv[0], LOG_PID, LOG_DAEMON);
if(argc!=4) {
syslog(LOG_WARNING, "Usage error");
return 1;
}
outfd=atoi(argv[3]);
mainwindow=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(mainwindow), "pppgetpass");
gtk_signal_connect(GTK_OBJECT(mainwindow), "destroy",
GTK_SIGNAL_FUNC(gtk_main_quit), 0);
vbox=gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(mainwindow), vbox);
gtk_widget_show(vbox);
if(argv[1][0] && argv[2][0])
snprintf(buf, sizeof buf, "Password for PPP client %s on server %s: ", argv[1], argv[2]);
else if(argv[1][0] && !argv[2][0])
snprintf(buf, sizeof buf, "Password for PPP client %s: ", argv[1]);
else if(!argv[1][0] && argv[2][0])
snprintf(buf, sizeof buf, "Password for PPP on server %s: ", argv[2]);
else
snprintf(buf, sizeof buf, "Enter PPP password: ");
question=gtk_label_new(buf);
gtk_box_pack_start(GTK_BOX(vbox), question, FALSE, TRUE, 0);
gtk_widget_show(question);
answer=gtk_entry_new();
gtk_entry_set_visibility(GTK_ENTRY(answer), 0);
gtk_box_pack_start(GTK_BOX(vbox), answer, FALSE, TRUE, 0);
gtk_widget_show(answer);
ok=gtk_button_new_with_label("OK");
gtk_box_pack_start(GTK_BOX(vbox), ok, FALSE, TRUE, 0);
gtk_signal_connect(GTK_OBJECT(ok), "clicked",
GTK_SIGNAL_FUNC(okpressed), answer);
gtk_widget_show(ok);
gtk_widget_show(mainwindow);
gtk_main();
return err;
}

View File

@ -0,0 +1,7 @@
#!/bin/sh
if [ -z "$DISPLAY" ]; then
exec pppgetpass.vt "$@"
else
exec pppgetpass.gtk "$@"
fi

View File

@ -0,0 +1,218 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <syslog.h>
#include <termios.h>
#include <sys/vt.h>
static int console_owner(uid_t, int);
int main(int argc, char **argv)
{
int console;
uid_t uid;
struct vt_stat origstate;
int openvtnum;
char openvtname[256];
int openvt;
gid_t gid;
int chowned;
FILE *fp;
struct termios t;
char pass[256], *nl;
int outfd, passlen;
ssize_t wrote;
console=open("/dev/console", O_RDWR);
uid=getuid();
gid=getgid();
seteuid(uid);
openlog(argv[0], LOG_PID, LOG_DAEMON);
if(argc!=4) {
syslog(LOG_WARNING, "Usage error");
return 1;
}
if(console<0) {
syslog(LOG_ERR, "open(/dev/console): %m");
return 1;
}
if(ioctl(console, VT_GETSTATE, &origstate)<0) {
syslog(LOG_ERR, "VT_GETSTATE: %m");
return 1;
}
if(uid) {
if(!console_owner(uid, origstate.v_active)) {
int i;
for(i=0;i<64;++i) {
if(i!=origstate.v_active && console_owner(uid, i))
break;
}
if(i==64) {
syslog(LOG_WARNING, "run by uid %lu not at console", (unsigned long)uid);
return 1;
}
}
}
if(ioctl(console, VT_OPENQRY, &openvtnum)<0) {
syslog(LOG_ERR, "VT_OPENQRY: %m");
return 1;
}
if(openvtnum==-1) {
syslog(LOG_ERR, "No free VTs");
return 1;
}
snprintf(openvtname, sizeof openvtname, "/dev/tty%d", openvtnum);
seteuid(0);
openvt=open(openvtname, O_RDWR);
if(openvt<0) {
seteuid(uid);
syslog(LOG_ERR, "open(%s): %m", openvtname);
return 1;
}
chowned=fchown(openvt, uid, gid);
if(chowned<0) {
seteuid(uid);
syslog(LOG_ERR, "fchown(%s): %m", openvtname);
return 1;
}
close(console);
if(ioctl(openvt, VT_ACTIVATE, openvtnum)<0) {
seteuid(uid);
syslog(LOG_ERR, "VT_ACTIVATE(%d): %m", openvtnum);
return 1;
}
while(ioctl(openvt, VT_WAITACTIVE, openvtnum)<0) {
if(errno!=EINTR) {
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "VT_WAITACTIVE(%d): %m", openvtnum);
return 1;
}
}
seteuid(uid);
fp=fdopen(openvt, "r+");
if(!fp) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "fdopen(%s): %m", openvtname);
return 1;
}
if(tcgetattr(openvt, &t)<0) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "tcgetattr(%s): %m", openvtname);
return 1;
}
t.c_lflag &= ~ECHO;
if(tcsetattr(openvt, TCSANOW, &t)<0) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "tcsetattr(%s): %m", openvtname);
return 1;
}
if(fprintf(fp, "\033[2J\033[H")<0) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "write error on %s: %m", openvtname);
return 1;
}
if(argv[1][0] && argv[2][0]) {
if(fprintf(fp, "Password for PPP client %s on server %s: ", argv[1], argv[2])<0) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "write error on %s: %m", openvtname);
return 1;
}
} else if(argv[1][0] && !argv[2][0]) {
if(fprintf(fp, "Password for PPP client %s: ", argv[1])<0) {
syslog(LOG_ERR, "write error on %s: %m", openvtname);
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
return 1;
}
} else if(!argv[1][0] && argv[2][0]) {
if(fprintf(fp, "Password for PPP on server %s: ", argv[2])<0) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "write error on %s: %m", openvtname);
return 1;
}
} else {
if(fprintf(fp, "Enter PPP password: ")<0) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
syslog(LOG_ERR, "write error on %s: %m", openvtname);
return 1;
}
}
if(!fgets(pass, sizeof pass, fp)) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
if(ferror(fp)) {
syslog(LOG_ERR, "read error on %s: %m", openvtname);
}
return 1;
}
if((nl=strchr(pass, '\n')))
*nl=0;
passlen=strlen(pass);
outfd=atoi(argv[3]);
if((wrote=write(outfd, pass, passlen))!=passlen) {
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
if(wrote<0)
syslog(LOG_ERR, "write error on outpipe: %m");
else
syslog(LOG_ERR, "short write on outpipe");
return 1;
}
seteuid(0);
ioctl(openvt, VT_ACTIVATE, origstate.v_active);
seteuid(uid);
return 0;
}
static int console_owner(uid_t uid, int cons)
{
char name[256];
struct stat st;
snprintf(name, sizeof name, "/dev/tty%d", cons);
if(stat(name, &st)<0) {
if(errno!=ENOENT)
syslog(LOG_ERR, "stat(%s): %m", name);
return 0;
}
return uid==st.st_uid;
}

2
etc.ppp/chap-secrets Normal file
View File

@ -0,0 +1,2 @@
# Secrets for authentication using CHAP
# client server secret IP addresses

1
etc.ppp/options Normal file
View File

@ -0,0 +1 @@
lock

2
etc.ppp/pap-secrets Normal file
View File

@ -0,0 +1,2 @@
# Secrets for authentication using PAP
# client server secret IP addresses

178
include/linux/if_ppp.h Normal file
View File

@ -0,0 +1,178 @@
/* $Id: if_ppp.h,v 1.23 2002/12/06 09:49:15 paulus Exp $ */
/*
* if_ppp.h - Point-to-Point Protocol definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/*
* ==FILEVERSION 20000724==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the above date.
* if_ppp.h is shipped with a PPP distribution as well as with the kernel;
* if everyone increases the FILEVERSION number above, then scripts
* can do the right thing when deciding whether to install a new if_ppp.h
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
*/
#ifndef _IF_PPP_H_
#define _IF_PPP_H_
/*
* Packet sizes
*/
#define PPP_MTU 1500 /* Default MTU (size of Info field) */
#define PPP_MAXMRU 65000 /* Largest MRU we allow */
#define PROTO_IPX 0x002b /* protocol numbers */
#define PROTO_DNA_RT 0x0027 /* DNA Routing */
/*
* Bit definitions for flags.
*/
#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */
#define SC_COMP_AC 0x00000002 /* header compression (output) */
#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */
#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */
#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */
#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */
#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */
#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */
#define SC_ENABLE_IP 0x00000100 /* IP packets may be exchanged */
#define SC_LOOP_TRAFFIC 0x00000200 /* send traffic to pppd */
#define SC_MULTILINK 0x00000400 /* do multilink encapsulation */
#define SC_MP_SHORTSEQ 0x00000800 /* use short MP sequence numbers */
#define SC_COMP_RUN 0x00001000 /* compressor has been inited */
#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */
#define SC_MP_XSHORTSEQ 0x00004000 /* transmit short MP seq numbers */
#define SC_DEBUG 0x00010000 /* enable debug messages */
#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */
#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */
#define SC_LOG_RAWIN 0x00080000 /* log all chars received */
#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */
#define SC_SYNC 0x00200000 /* synchronous serial mode */
#define SC_MASK 0x0f200fff /* bits that user can change */
/* state bits */
#define SC_XMIT_BUSY 0x10000000 /* (used by isdn_ppp?) */
#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */
#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */
#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */
#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */
#define SC_DC_FERROR 0x00800000 /* fatal decomp error detected */
#define SC_DC_ERROR 0x00400000 /* non-fatal decomp error detected */
/*
* Ioctl definitions.
*/
struct npioctl {
int protocol; /* PPP protocol, e.g. PPP_IP */
enum NPmode mode;
};
/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */
struct ppp_option_data {
__u8 *ptr;
__u32 length;
int transmit;
};
struct ifpppstatsreq {
struct ifreq b;
struct ppp_stats stats; /* statistic information */
};
struct ifpppcstatsreq {
struct ifreq b;
struct ppp_comp_stats stats;
};
#define ifr__name b.ifr_ifrn.ifrn_name
#define stats_ptr b.ifr_ifru.ifru_data
/*
* Ioctl definitions.
*/
#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */
#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */
#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */
#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */
#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */
#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */
#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */
#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */
#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */
#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */
#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */
#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */
#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
#define PPPIOCSPASS _IOW('t', 71, struct sock_fprog) /* set pass filter */
#define PPPIOCSACTIVE _IOW('t', 70, struct sock_fprog) /* set active filt */
#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */
#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */
#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */
#define PPPIOCNEWUNIT _IOWR('t', 62, int) /* create new ppp unit */
#define PPPIOCATTACH _IOW('t', 61, int) /* attach to ppp unit */
#define PPPIOCDETACH _IOW('t', 60, int) /* detach from ppp unit/chan */
#define PPPIOCSMRRU _IOW('t', 59, int) /* set multilink MRU */
#define PPPIOCCONNECT _IOW('t', 58, int) /* connect channel to unit */
#define PPPIOCDISCONN _IO('t', 57) /* disconnect channel */
#define PPPIOCATTCHAN _IOW('t', 56, int) /* attach to ppp channel */
#define PPPIOCGCHAN _IOR('t', 55, int) /* get ppp channel number */
#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0)
#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */
#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2)
#if !defined(ifr_mtu)
#define ifr_mtu ifr_ifru.ifru_metric
#endif
#endif /* _IF_PPP_H_ */

213
include/linux/ppp-comp.h Normal file
View File

@ -0,0 +1,213 @@
/*
* ppp-comp.h - Definitions for doing PPP packet compression.
*
* Copyright (c) 1984 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: ppp-comp.h,v 1.10 2002/12/06 09:49:15 paulus Exp $
*/
/*
* ==FILEVERSION 20020319==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the above date.
* ppp-comp.h is shipped with a PPP distribution as well as with the kernel;
* if everyone increases the FILEVERSION number above, then scripts
* can do the right thing when deciding whether to install a new ppp-comp.h
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
*/
#ifndef _NET_PPP_COMP_H
#define _NET_PPP_COMP_H
/*
* The following symbols control whether we include code for
* various compression methods.
*/
#ifndef DO_BSD_COMPRESS
#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */
#endif
#ifndef DO_DEFLATE
#define DO_DEFLATE 1 /* by default, include Deflate */
#endif
#define DO_PREDICTOR_1 0
#define DO_PREDICTOR_2 0
/*
* Structure giving methods for compression/decompression.
*/
struct compressor {
int compress_proto; /* CCP compression protocol number */
/* Allocate space for a compressor (transmit side) */
void *(*comp_alloc) (unsigned char *options, int opt_len);
/* Free space used by a compressor */
void (*comp_free) (void *state);
/* Initialize a compressor */
int (*comp_init) (void *state, unsigned char *options,
int opt_len, int unit, int opthdr, int debug);
/* Reset a compressor */
void (*comp_reset) (void *state);
/* Compress a packet */
int (*compress) (void *state, unsigned char *rptr,
unsigned char *obuf, int isize, int osize);
/* Return compression statistics */
void (*comp_stat) (void *state, struct compstat *stats);
/* Allocate space for a decompressor (receive side) */
void *(*decomp_alloc) (unsigned char *options, int opt_len);
/* Free space used by a decompressor */
void (*decomp_free) (void *state);
/* Initialize a decompressor */
int (*decomp_init) (void *state, unsigned char *options,
int opt_len, int unit, int opthdr, int mru,
int debug);
/* Reset a decompressor */
void (*decomp_reset) (void *state);
/* Decompress a packet. */
int (*decompress) (void *state, unsigned char *ibuf, int isize,
unsigned char *obuf, int osize);
/* Update state for an incompressible packet received */
void (*incomp) (void *state, unsigned char *ibuf, int icnt);
/* Return decompression statistics */
void (*decomp_stat) (void *state, struct compstat *stats);
};
/*
* The return value from decompress routine is the length of the
* decompressed packet if successful, otherwise DECOMP_ERROR
* or DECOMP_FATALERROR if an error occurred.
*
* We need to make this distinction so that we can disable certain
* useful functionality, namely sending a CCP reset-request as a result
* of an error detected after decompression. This is to avoid infringing
* a patent held by Motorola.
* Don't you just lurve software patents.
*/
#define DECOMP_ERROR -1 /* error detected before decomp. */
#define DECOMP_FATALERROR -2 /* error detected after decomp. */
/*
* CCP codes.
*/
#define CCP_CONFREQ 1
#define CCP_CONFACK 2
#define CCP_TERMREQ 5
#define CCP_TERMACK 6
#define CCP_RESETREQ 14
#define CCP_RESETACK 15
/*
* Max # bytes for a CCP option
*/
#define CCP_MAX_OPTION_LENGTH 32
/*
* Parts of a CCP packet.
*/
#define CCP_CODE(dp) ((dp)[0])
#define CCP_ID(dp) ((dp)[1])
#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3])
#define CCP_HDRLEN 4
#define CCP_OPT_CODE(dp) ((dp)[0])
#define CCP_OPT_LENGTH(dp) ((dp)[1])
#define CCP_OPT_MINLEN 2
/*
* Definitions for BSD-Compress.
*/
#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */
#define CILEN_BSD_COMPRESS 3 /* length of config. option */
/* Macros for handling the 3rd byte of the BSD-Compress config option. */
#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */
#define BSD_VERSION(x) ((x) >> 5) /* version of option format */
#define BSD_CURRENT_VERSION 1 /* current version number */
#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n))
#define BSD_MIN_BITS 9 /* smallest code size supported */
#define BSD_MAX_BITS 15 /* largest code size supported */
/*
* Definitions for Deflate.
*/
#define CI_DEFLATE 26 /* config option for Deflate */
#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */
#define CILEN_DEFLATE 4 /* length of its config option */
#define DEFLATE_MIN_SIZE 8
#define DEFLATE_MAX_SIZE 15
#define DEFLATE_METHOD_VAL 8
#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
#define DEFLATE_METHOD(x) ((x) & 0x0F)
#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
+ DEFLATE_METHOD_VAL)
#define DEFLATE_CHK_SEQUENCE 0
/*
* Definitions for MPPE.
*/
#define CI_MPPE 18 /* config option for MPPE */
#define CILEN_MPPE 6 /* length of config option */
/*
* Definitions for other, as yet unsupported, compression methods.
*/
#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */
#define CILEN_PREDICTOR_1 2 /* length of its config option */
#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */
#define CILEN_PREDICTOR_2 2 /* length of its config option */
#endif /* _NET_PPP_COMP_H */

195
include/linux/ppp_defs.h Normal file
View File

@ -0,0 +1,195 @@
/* $Id: ppp_defs.h,v 1.11 2002/12/06 09:49:15 paulus Exp $ */
/*
* ppp_defs.h - PPP definitions.
*
* Copyright (c) 1989-2002 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* ==FILEVERSION 20020521==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the above date.
* ppp_defs.h is shipped with a PPP distribution as well as with the kernel;
* if everyone increases the FILEVERSION number above, then scripts
* can do the right thing when deciding whether to install a new ppp_defs.h
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
*/
#ifndef _PPP_DEFS_H_
#define _PPP_DEFS_H_
/*
* The basic PPP frame.
*/
#define PPP_HDRLEN 4 /* octets for standard ppp header */
#define PPP_FCSLEN 2 /* octets for FCS */
#define PPP_MRU 1500 /* default MRU = max length of info field */
#define PPP_ADDRESS(p) (((__u8 *)(p))[0])
#define PPP_CONTROL(p) (((__u8 *)(p))[1])
#define PPP_PROTOCOL(p) ((((__u8 *)(p))[2] << 8) + ((__u8 *)(p))[3])
/*
* Significant octet values.
*/
#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
#define PPP_UI 0x03 /* Unnumbered Information */
#define PPP_FLAG 0x7e /* Flag Sequence */
#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
/*
* Protocol field values.
*/
#define PPP_IP 0x21 /* Internet Protocol */
#define PPP_AT 0x29 /* AppleTalk Protocol */
#define PPP_IPX 0x2b /* IPX protocol */
#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
#define PPP_MP 0x3d /* Multilink protocol */
#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */
#define PPP_COMPFRAG 0xfb /* fragment compressed below bundle */
#define PPP_COMP 0xfd /* compressed packet */
#define PPP_IPCP 0x8021 /* IP Control Protocol */
#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
#define PPP_IPXCP 0x802b /* IPX Control Protocol */
#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
#define PPP_CCPFRAG 0x80fb /* CCP at link level (below MP bundle) */
#define PPP_CCP 0x80fd /* Compression Control Protocol */
#define PPP_ECPFRAG 0x8055 /* ECP at link level (below MP bundle) */
#define PPP_ECP 0x8053 /* Encryption Control Protocol */
#define PPP_LCP 0xc021 /* Link Control Protocol */
#define PPP_PAP 0xc023 /* Password Authentication Protocol */
#define PPP_LQR 0xc025 /* Link Quality Report protocol */
#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
#define PPP_CBCP 0xc029 /* Callback Control Protocol */
/*
* Values for FCS calculations.
*/
#define PPP_INITFCS 0xffff /* Initial FCS value */
#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
/*
* Extended asyncmap - allows any character to be escaped.
*/
typedef __u32 ext_accm[8];
/*
* What to do with network protocol (NP) packets.
*/
enum NPmode {
NPMODE_PASS, /* pass the packet through */
NPMODE_DROP, /* silently drop the packet */
NPMODE_ERROR, /* return an error */
NPMODE_QUEUE /* save it up for later. */
};
/*
* Statistics for LQRP and pppstats
*/
struct pppstat {
__u32 ppp_discards; /* # frames discarded */
__u32 ppp_ibytes; /* bytes received */
__u32 ppp_ioctects; /* bytes received not in error */
__u32 ppp_ipackets; /* packets received */
__u32 ppp_ierrors; /* receive errors */
__u32 ppp_ilqrs; /* # LQR frames received */
__u32 ppp_obytes; /* raw bytes sent */
__u32 ppp_ooctects; /* frame bytes sent */
__u32 ppp_opackets; /* packets sent */
__u32 ppp_oerrors; /* transmit errors */
__u32 ppp_olqrs; /* # LQR frames sent */
};
struct vjstat {
__u32 vjs_packets; /* outbound packets */
__u32 vjs_compressed; /* outbound compressed packets */
__u32 vjs_searches; /* searches for connection state */
__u32 vjs_misses; /* times couldn't find conn. state */
__u32 vjs_uncompressedin; /* inbound uncompressed packets */
__u32 vjs_compressedin; /* inbound compressed packets */
__u32 vjs_errorin; /* inbound unknown type packets */
__u32 vjs_tossed; /* inbound packets tossed because of error */
};
struct compstat {
__u32 unc_bytes; /* total uncompressed bytes */
__u32 unc_packets; /* total uncompressed packets */
__u32 comp_bytes; /* compressed bytes */
__u32 comp_packets; /* compressed packets */
__u32 inc_bytes; /* incompressible bytes */
__u32 inc_packets; /* incompressible packets */
/* the compression ratio is defined as in_count / bytes_out */
__u32 in_count; /* Bytes received */
__u32 bytes_out; /* Bytes transmitted */
double ratio; /* not computed in kernel. */
};
struct ppp_stats {
struct pppstat p; /* basic PPP statistics */
struct vjstat vj; /* VJ header compression statistics */
};
struct ppp_comp_stats {
struct compstat c; /* packet compression statistics */
struct compstat d; /* packet decompression statistics */
};
/*
* The following structure records the time in seconds since
* the last NP packet was sent or received.
*/
struct ppp_idle {
time_t xmit_idle; /* time since last NP packet sent */
time_t recv_idle; /* time since last NP packet received */
};
#ifndef __P
#ifdef __STDC__
#define __P(x) x
#else
#define __P(x) ()
#endif
#endif
#endif /* _PPP_DEFS_H_ */

156
include/net/if_ppp.h Normal file
View File

@ -0,0 +1,156 @@
/* $Id: if_ppp.h,v 1.19 2002/12/06 09:49:15 paulus Exp $ */
/*
* if_ppp.h - Point-to-Point Protocol definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _IF_PPP_H_
#define _IF_PPP_H_
/*
* Bit definitions for flags.
*/
#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */
#define SC_COMP_AC 0x00000002 /* header compression (output) */
#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */
#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */
#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */
#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */
#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */
#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */
#define SC_DEBUG 0x00010000 /* enable debug messages */
#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */
#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */
#define SC_LOG_RAWIN 0x00080000 /* log all chars received */
#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */
#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */
#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */
#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */
#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */
#define SC_SYNC 0x00200000 /* use synchronous HDLC framing */
#define SC_MASK 0x0fff00ff /* bits that user can change */
/*
* State bits in sc_flags, not changeable by user.
*/
#define SC_TIMEOUT 0x00000400 /* timeout is currently pending */
#define SC_VJ_RESET 0x00000800 /* need to reset VJ decomp */
#define SC_COMP_RUN 0x00001000 /* compressor has been inited */
#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */
#define SC_DC_ERROR 0x00004000 /* non-fatal decomp error detected */
#define SC_DC_FERROR 0x00008000 /* fatal decomp error detected */
#define SC_TBUSY 0x10000000 /* xmitter doesn't need a packet yet */
#define SC_PKTLOST 0x20000000 /* have lost or dropped a packet */
#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */
#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */
/*
* Ioctl definitions.
*/
struct npioctl {
int protocol; /* PPP procotol, e.g. PPP_IP */
enum NPmode mode;
};
/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */
struct ppp_option_data {
u_char *ptr;
u_int length;
int transmit;
};
struct ifpppstatsreq {
char ifr_name[IFNAMSIZ];
struct ppp_stats stats;
};
struct ifpppcstatsreq {
char ifr_name[IFNAMSIZ];
struct ppp_comp_stats stats;
};
/*
* Ioctl definitions.
*/
#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */
#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */
#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */
#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */
#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */
#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */
#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */
#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */
#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */
#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */
#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */
#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */
#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
#define PPPIOCGIDLE _IOR('t', 74, struct ppp_idle) /* get idle time */
#ifdef PPP_FILTER
#define PPPIOCSPASS _IOW('t', 71, struct bpf_program) /* set pass filter */
#define PPPIOCSACTIVE _IOW('t', 70, struct bpf_program) /* set active filt */
#endif /* PPP_FILTER */
/* PPPIOC[GS]MTU are alternatives to SIOC[GS]IFMTU, used under Ultrix */
#define PPPIOCGMTU _IOR('t', 73, int) /* get interface MTU */
#define PPPIOCSMTU _IOW('t', 72, int) /* set interface MTU */
/*
* These two are interface ioctls so that pppstats can do them on
* a socket without having to open the serial device.
*/
#define SIOCGPPPSTATS _IOWR('i', 123, struct ifpppstatsreq)
#define SIOCGPPPCSTATS _IOWR('i', 122, struct ifpppcstatsreq)
#if !defined(ifr_mtu)
#define ifr_mtu ifr_ifru.ifru_metric
#endif
#if (defined(_KERNEL) || defined(KERNEL)) && !defined(NeXT)
void pppattach __P((void));
void pppintr __P((void));
#endif
#endif /* _IF_PPP_H_ */

179
include/net/ppp-comp.h Normal file
View File

@ -0,0 +1,179 @@
/*
* ppp-comp.h - Definitions for doing PPP packet compression.
*
* Copyright (c) 1984 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: ppp-comp.h,v 1.13 2002/12/06 09:49:15 paulus Exp $
*/
#ifndef _NET_PPP_COMP_H
#define _NET_PPP_COMP_H
/*
* The following symbols control whether we include code for
* various compression methods.
*/
#ifndef DO_BSD_COMPRESS
#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */
#endif
#ifndef DO_DEFLATE
#define DO_DEFLATE 1 /* by default, include Deflate */
#endif
#define DO_PREDICTOR_1 0
#define DO_PREDICTOR_2 0
/*
* Structure giving methods for compression/decompression.
*/
#ifdef PACKETPTR
struct compressor {
int compress_proto; /* CCP compression protocol number */
/* Allocate space for a compressor (transmit side) */
void *(*comp_alloc) __P((u_char *options, int opt_len));
/* Free space used by a compressor */
void (*comp_free) __P((void *state));
/* Initialize a compressor */
int (*comp_init) __P((void *state, u_char *options, int opt_len,
int unit, int hdrlen, int debug));
/* Reset a compressor */
void (*comp_reset) __P((void *state));
/* Compress a packet */
int (*compress) __P((void *state, PACKETPTR *mret,
PACKETPTR mp, int orig_len, int max_len));
/* Return compression statistics */
void (*comp_stat) __P((void *state, struct compstat *stats));
/* Allocate space for a decompressor (receive side) */
void *(*decomp_alloc) __P((u_char *options, int opt_len));
/* Free space used by a decompressor */
void (*decomp_free) __P((void *state));
/* Initialize a decompressor */
int (*decomp_init) __P((void *state, u_char *options, int opt_len,
int unit, int hdrlen, int mru, int debug));
/* Reset a decompressor */
void (*decomp_reset) __P((void *state));
/* Decompress a packet. */
int (*decompress) __P((void *state, PACKETPTR mp,
PACKETPTR *dmpp));
/* Update state for an incompressible packet received */
void (*incomp) __P((void *state, PACKETPTR mp));
/* Return decompression statistics */
void (*decomp_stat) __P((void *state, struct compstat *stats));
};
#endif /* PACKETPTR */
/*
* Return values for decompress routine.
* We need to make these distinctions so that we can disable certain
* useful functionality, namely sending a CCP reset-request as a result
* of an error detected after decompression. This is to avoid infringing
* a patent held by Motorola.
* Don't you just lurve software patents.
*/
#define DECOMP_OK 0 /* everything went OK */
#define DECOMP_ERROR 1 /* error detected before decomp. */
#define DECOMP_FATALERROR 2 /* error detected after decomp. */
/*
* CCP codes.
*/
#define CCP_CONFREQ 1
#define CCP_CONFACK 2
#define CCP_TERMREQ 5
#define CCP_TERMACK 6
#define CCP_RESETREQ 14
#define CCP_RESETACK 15
/*
* Max # bytes for a CCP option
*/
#define CCP_MAX_OPTION_LENGTH 32
/*
* Parts of a CCP packet.
*/
#define CCP_CODE(dp) ((dp)[0])
#define CCP_ID(dp) ((dp)[1])
#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3])
#define CCP_HDRLEN 4
#define CCP_OPT_CODE(dp) ((dp)[0])
#define CCP_OPT_LENGTH(dp) ((dp)[1])
#define CCP_OPT_MINLEN 2
/*
* Definitions for BSD-Compress.
*/
#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */
#define CILEN_BSD_COMPRESS 3 /* length of config. option */
/* Macros for handling the 3rd byte of the BSD-Compress config option. */
#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */
#define BSD_VERSION(x) ((x) >> 5) /* version of option format */
#define BSD_CURRENT_VERSION 1 /* current version number */
#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n))
#define BSD_MIN_BITS 9 /* smallest code size supported */
#define BSD_MAX_BITS 15 /* largest code size supported */
/*
* Definitions for Deflate.
*/
#define CI_DEFLATE 26 /* config option for Deflate */
#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */
#define CILEN_DEFLATE 4 /* length of its config option */
#define DEFLATE_MIN_SIZE 8
#define DEFLATE_MAX_SIZE 15
#define DEFLATE_METHOD_VAL 8
#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
#define DEFLATE_METHOD(x) ((x) & 0x0F)
#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
+ DEFLATE_METHOD_VAL)
#define DEFLATE_CHK_SEQUENCE 0
/*
* Definitions for MPPE.
*/
#define CI_MPPE 18 /* config option for MPPE */
#define CILEN_MPPE 6 /* length of config option */
/*
* Definitions for other, as yet unsupported, compression methods.
*/
#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */
#define CILEN_PREDICTOR_1 2 /* length of its config option */
#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */
#define CILEN_PREDICTOR_2 2 /* length of its config option */
#endif /* _NET_PPP_COMP_H */

194
include/net/ppp_defs.h Normal file
View File

@ -0,0 +1,194 @@
/* $Id: ppp_defs.h,v 1.17 2002/12/06 09:49:15 paulus Exp $ */
/*
* ppp_defs.h - PPP definitions.
*
* Copyright (c) 1984 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _PPP_DEFS_H_
#define _PPP_DEFS_H_
/*
* The basic PPP frame.
*/
#define PPP_HDRLEN 4 /* octets for standard ppp header */
#define PPP_FCSLEN 2 /* octets for FCS */
/*
* Packet sizes
*
* Note - lcp shouldn't be allowed to negotiate stuff outside these
* limits. See lcp.h in the pppd directory.
* (XXX - these constants should simply be shared by lcp.c instead
* of living in lcp.h)
*/
#define PPP_MTU 1500 /* Default MTU (size of Info field) */
#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN)
#define PPP_MINMTU 64
#define PPP_MRU 1500 /* default MRU = max length of info field */
#define PPP_MAXMRU 65000 /* Largest MRU we allow */
#define PPP_MINMRU 128
#define PPP_ADDRESS(p) (((u_char *)(p))[0])
#define PPP_CONTROL(p) (((u_char *)(p))[1])
#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
/*
* Significant octet values.
*/
#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
#define PPP_UI 0x03 /* Unnumbered Information */
#define PPP_FLAG 0x7e /* Flag Sequence */
#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
/*
* Protocol field values.
*/
#define PPP_IP 0x21 /* Internet Protocol */
#define PPP_AT 0x29 /* AppleTalk Protocol */
#define PPP_IPX 0x2b /* IPX protocol */
#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */
#define PPP_COMP 0xfd /* compressed packet */
#define PPP_IPCP 0x8021 /* IP Control Protocol */
#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
#define PPP_IPXCP 0x802b /* IPX Control Protocol */
#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
#define PPP_CCP 0x80fd /* Compression Control Protocol */
#define PPP_ECP 0x8053 /* Encryption Control Protocol */
#define PPP_LCP 0xc021 /* Link Control Protocol */
#define PPP_PAP 0xc023 /* Password Authentication Protocol */
#define PPP_LQR 0xc025 /* Link Quality Report protocol */
#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
#define PPP_CBCP 0xc029 /* Callback Control Protocol */
#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */
/*
* Values for FCS calculations.
*/
#define PPP_INITFCS 0xffff /* Initial FCS value */
#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
/*
* A 32-bit unsigned integral type.
*/
#if !defined(__BIT_TYPES_DEFINED__) && !defined(_BITYPES) \
&& !defined(__FreeBSD__) && (NS_TARGET < 40)
#ifdef UINT32_T
typedef UINT32_T u_int32_t;
#else
typedef unsigned int u_int32_t;
typedef unsigned short u_int16_t;
#endif
#endif
/*
* Extended asyncmap - allows any character to be escaped.
*/
typedef u_int32_t ext_accm[8];
/*
* What to do with network protocol (NP) packets.
*/
enum NPmode {
NPMODE_PASS, /* pass the packet through */
NPMODE_DROP, /* silently drop the packet */
NPMODE_ERROR, /* return an error */
NPMODE_QUEUE /* save it up for later. */
};
/*
* Statistics.
*/
struct pppstat {
unsigned int ppp_ibytes; /* bytes received */
unsigned int ppp_ipackets; /* packets received */
unsigned int ppp_ierrors; /* receive errors */
unsigned int ppp_obytes; /* bytes sent */
unsigned int ppp_opackets; /* packets sent */
unsigned int ppp_oerrors; /* transmit errors */
};
struct vjstat {
unsigned int vjs_packets; /* outbound packets */
unsigned int vjs_compressed; /* outbound compressed packets */
unsigned int vjs_searches; /* searches for connection state */
unsigned int vjs_misses; /* times couldn't find conn. state */
unsigned int vjs_uncompressedin; /* inbound uncompressed packets */
unsigned int vjs_compressedin; /* inbound compressed packets */
unsigned int vjs_errorin; /* inbound unknown type packets */
unsigned int vjs_tossed; /* inbound packets tossed because of error */
};
struct ppp_stats {
struct pppstat p; /* basic PPP statistics */
struct vjstat vj; /* VJ header compression statistics */
};
struct compstat {
unsigned int unc_bytes; /* total uncompressed bytes */
unsigned int unc_packets; /* total uncompressed packets */
unsigned int comp_bytes; /* compressed bytes */
unsigned int comp_packets; /* compressed packets */
unsigned int inc_bytes; /* incompressible bytes */
unsigned int inc_packets; /* incompressible packets */
unsigned int ratio; /* recent compression ratio << 8 */
};
struct ppp_comp_stats {
struct compstat c; /* packet compression statistics */
struct compstat d; /* packet decompression statistics */
};
/*
* The following structure records the time in seconds since
* the last NP packet was sent or received.
*/
struct ppp_idle {
time_t xmit_idle; /* time since last NP packet sent */
time_t recv_idle; /* time since last NP packet received */
};
#ifndef __P
#ifdef __STDC__
#define __P(x) x
#else
#define __P(x) ()
#endif
#endif
#endif /* _PPP_DEFS_H_ */

107
include/net/pppio.h Normal file
View File

@ -0,0 +1,107 @@
/*
* pppio.h - ioctl and other misc. definitions for STREAMS modules.
*
* Copyright (c) 1994 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: pppio.h,v 1.9 2002/12/06 09:49:15 paulus Exp $
*/
#define _PPPIO(n) (('p' << 8) + (n))
#define PPPIO_NEWPPA _PPPIO(130) /* allocate a new PPP unit */
#define PPPIO_GETSTAT _PPPIO(131) /* get PPP statistics */
#define PPPIO_GETCSTAT _PPPIO(132) /* get PPP compression stats */
#define PPPIO_MTU _PPPIO(133) /* set max transmission unit */
#define PPPIO_MRU _PPPIO(134) /* set max receive unit */
#define PPPIO_CFLAGS _PPPIO(135) /* set/clear/get compression flags */
#define PPPIO_XCOMP _PPPIO(136) /* alloc transmit compressor */
#define PPPIO_RCOMP _PPPIO(137) /* alloc receive decompressor */
#define PPPIO_XACCM _PPPIO(138) /* set transmit asyncmap */
#define PPPIO_RACCM _PPPIO(139) /* set receive asyncmap */
#define PPPIO_VJINIT _PPPIO(140) /* initialize VJ comp/decomp */
#define PPPIO_ATTACH _PPPIO(141) /* attach to a ppa (without putmsg) */
#define PPPIO_LASTMOD _PPPIO(142) /* mark last ppp module */
#define PPPIO_GCLEAN _PPPIO(143) /* get 8-bit-clean flags */
#define PPPIO_DEBUG _PPPIO(144) /* request debug information */
#define PPPIO_BIND _PPPIO(145) /* bind to SAP */
#define PPPIO_NPMODE _PPPIO(146) /* set mode for handling data pkts */
#define PPPIO_GIDLE _PPPIO(147) /* get time since last data pkt */
#define PPPIO_PASSFILT _PPPIO(148) /* set filter for packets to pass */
#define PPPIO_ACTIVEFILT _PPPIO(149) /* set filter for "link active" pkts */
/*
* Values for PPPIO_CFLAGS
*/
#define COMP_AC 0x1 /* compress address/control */
#define DECOMP_AC 0x2 /* decompress address/control */
#define COMP_PROT 0x4 /* compress PPP protocol */
#define DECOMP_PROT 0x8 /* decompress PPP protocol */
#define COMP_VJC 0x10 /* compress TCP/IP headers */
#define COMP_VJCCID 0x20 /* compress connection ID as well */
#define DECOMP_VJC 0x40 /* decompress TCP/IP headers */
#define DECOMP_VJCCID 0x80 /* accept compressed connection ID */
#define CCP_ISOPEN 0x100 /* look at CCP packets */
#define CCP_ISUP 0x200 /* do packet comp/decomp */
#define CCP_ERROR 0x400 /* (status) error in packet decomp */
#define CCP_FATALERROR 0x800 /* (status) fatal error ditto */
#define CCP_COMP_RUN 0x1000 /* (status) seen CCP ack sent */
#define CCP_DECOMP_RUN 0x2000 /* (status) seen CCP ack rcvd */
/*
* Values for 8-bit-clean flags.
*/
#define RCV_B7_0 1 /* have rcvd char with bit 7 = 0 */
#define RCV_B7_1 2 /* have rcvd char with bit 7 = 1 */
#define RCV_EVNP 4 /* have rcvd char with even parity */
#define RCV_ODDP 8 /* have rcvd char with odd parity */
/*
* Values for the first byte of M_CTL messages passed between
* PPP modules.
*/
#define PPPCTL_OERROR 0xe0 /* output error [up] */
#define PPPCTL_IERROR 0xe1 /* input error (e.g. FCS) [up] */
#define PPPCTL_MTU 0xe2 /* set MTU [down] */
#define PPPCTL_MRU 0xe3 /* set MRU [down] */
#define PPPCTL_UNIT 0xe4 /* note PPP unit number [down] */
/*
* Values for the integer argument to PPPIO_DEBUG.
*/
#define PPPDBG_DUMP 0x10000 /* print out debug info now */
#define PPPDBG_LOG 0x100 /* log various things */
#define PPPDBG_DRIVER 0 /* identifies ppp driver as target */
#define PPPDBG_IF 1 /* identifies ppp network i/f target */
#define PPPDBG_COMP 2 /* identifies ppp compression target */
#define PPPDBG_AHDLC 3 /* identifies ppp async hdlc target */

148
include/net/slcompress.h Normal file
View File

@ -0,0 +1,148 @@
/*
* Definitions for tcp compression routines.
*
* $Id: slcompress.h,v 1.4 1994/09/21 06:50:08 paulus Exp $
*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
#ifndef _SLCOMPRESS_H_
#define _SLCOMPRESS_H_
#define MAX_STATES 16 /* must be > 2 and < 256 */
#define MAX_HDR MLEN /* XXX 4bsd-ism: should really be 128 */
/*
* Compressed packet format:
*
* The first octet contains the packet type (top 3 bits), TCP
* 'push' bit, and flags that indicate which of the 4 TCP sequence
* numbers have changed (bottom 5 bits). The next octet is a
* conversation number that associates a saved IP/TCP header with
* the compressed packet. The next two octets are the TCP checksum
* from the original datagram. The next 0 to 15 octets are
* sequence number changes, one change per bit set in the header
* (there may be no changes and there are two special cases where
* the receiver implicitly knows what changed -- see below).
*
* There are 5 numbers which can change (they are always inserted
* in the following order): TCP urgent pointer, window,
* acknowlegement, sequence number and IP ID. (The urgent pointer
* is different from the others in that its value is sent, not the
* change in value.) Since typical use of SLIP links is biased
* toward small packets (see comments on MTU/MSS below), changes
* use a variable length coding with one octet for numbers in the
* range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
* range 256 - 65535 or 0. (If the change in sequence number or
* ack is more than 65535, an uncompressed packet is sent.)
*/
/*
* Packet types (must not conflict with IP protocol version)
*
* The top nibble of the first octet is the packet type. There are
* three possible types: IP (not proto TCP or tcp with one of the
* control flags set); uncompressed TCP (a normal IP/TCP packet but
* with the 8-bit protocol field replaced by an 8-bit connection id --
* this type of packet syncs the sender & receiver); and compressed
* TCP (described above).
*
* LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
* is logically part of the 4-bit "changes" field that follows. Top
* three bits are actual packet type. For backward compatibility
* and in the interest of conserving bits, numbers are chosen so the
* IP protocol version number (4) which normally appears in this nibble
* means "IP packet".
*/
/* packet types */
#define TYPE_IP 0x40
#define TYPE_UNCOMPRESSED_TCP 0x70
#define TYPE_COMPRESSED_TCP 0x80
#define TYPE_ERROR 0x00
/* Bits in first octet of compressed packet */
#define NEW_C 0x40 /* flag bits for what changed in a packet */
#define NEW_I 0x20
#define NEW_S 0x08
#define NEW_A 0x04
#define NEW_W 0x02
#define NEW_U 0x01
/* reserved, special-case values of above */
#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
#define TCP_PUSH_BIT 0x10
/*
* "state" data for each active tcp conversation on the wire. This is
* basically a copy of the entire IP/TCP header from the last packet
* we saw from the conversation together with a small identifier
* the transmit & receive ends of the line use to locate saved header.
*/
struct cstate {
struct cstate *cs_next; /* next most recently used cstate (xmit only) */
u_short cs_hlen; /* size of hdr (receive only) */
u_char cs_id; /* connection # associated with this state */
u_char cs_filler;
union {
char csu_hdr[MAX_HDR];
struct ip csu_ip; /* ip/tcp hdr from most recent packet */
} slcs_u;
};
#define cs_ip slcs_u.csu_ip
#define cs_hdr slcs_u.csu_hdr
/*
* all the state data for one serial line (we need one of these
* per line).
*/
struct slcompress {
struct cstate *last_cs; /* most recently used tstate */
u_char last_recv; /* last rcvd conn. id */
u_char last_xmit; /* last sent conn. id */
u_short flags;
#ifndef SL_NO_STATS
int sls_packets; /* outbound packets */
int sls_compressed; /* outbound compressed packets */
int sls_searches; /* searches for connection state */
int sls_misses; /* times couldn't find conn. state */
int sls_uncompressedin; /* inbound uncompressed packets */
int sls_compressedin; /* inbound compressed packets */
int sls_errorin; /* inbound unknown type packets */
int sls_tossed; /* inbound packets tossed because of error */
#endif
struct cstate tstate[MAX_STATES]; /* xmit connection states */
struct cstate rstate[MAX_STATES]; /* receive connection states */
};
/* flag values */
#define SLF_TOSS 1 /* tossing rcvd frames because of input err */
void sl_compress_init __P((struct slcompress *));
void sl_compress_setup __P((struct slcompress *, int));
u_int sl_compress_tcp __P((struct mbuf *,
struct ip *, struct slcompress *, int));
int sl_uncompress_tcp __P((u_char **, int, u_int, struct slcompress *));
int sl_uncompress_tcp_core __P((u_char *, int, int, u_int,
struct slcompress *, u_char **, u_int *));
#endif /* _SLCOMPRESS_H_ */

144
include/net/vjcompress.h Normal file
View File

@ -0,0 +1,144 @@
/*
* Definitions for tcp compression routines.
*
* $Id: vjcompress.h,v 1.3 1996/05/28 00:55:33 paulus Exp $
*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
#ifndef _VJCOMPRESS_H_
#define _VJCOMPRESS_H_
#define MAX_STATES 16 /* must be > 2 and < 256 */
#define MAX_HDR 128
/*
* Compressed packet format:
*
* The first octet contains the packet type (top 3 bits), TCP
* 'push' bit, and flags that indicate which of the 4 TCP sequence
* numbers have changed (bottom 5 bits). The next octet is a
* conversation number that associates a saved IP/TCP header with
* the compressed packet. The next two octets are the TCP checksum
* from the original datagram. The next 0 to 15 octets are
* sequence number changes, one change per bit set in the header
* (there may be no changes and there are two special cases where
* the receiver implicitly knows what changed -- see below).
*
* There are 5 numbers which can change (they are always inserted
* in the following order): TCP urgent pointer, window,
* acknowlegement, sequence number and IP ID. (The urgent pointer
* is different from the others in that its value is sent, not the
* change in value.) Since typical use of SLIP links is biased
* toward small packets (see comments on MTU/MSS below), changes
* use a variable length coding with one octet for numbers in the
* range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
* range 256 - 65535 or 0. (If the change in sequence number or
* ack is more than 65535, an uncompressed packet is sent.)
*/
/*
* Packet types (must not conflict with IP protocol version)
*
* The top nibble of the first octet is the packet type. There are
* three possible types: IP (not proto TCP or tcp with one of the
* control flags set); uncompressed TCP (a normal IP/TCP packet but
* with the 8-bit protocol field replaced by an 8-bit connection id --
* this type of packet syncs the sender & receiver); and compressed
* TCP (described above).
*
* LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
* is logically part of the 4-bit "changes" field that follows. Top
* three bits are actual packet type. For backward compatibility
* and in the interest of conserving bits, numbers are chosen so the
* IP protocol version number (4) which normally appears in this nibble
* means "IP packet".
*/
/* packet types */
#define TYPE_IP 0x40
#define TYPE_UNCOMPRESSED_TCP 0x70
#define TYPE_COMPRESSED_TCP 0x80
#define TYPE_ERROR 0x00
/* Bits in first octet of compressed packet */
#define NEW_C 0x40 /* flag bits for what changed in a packet */
#define NEW_I 0x20
#define NEW_S 0x08
#define NEW_A 0x04
#define NEW_W 0x02
#define NEW_U 0x01
/* reserved, special-case values of above */
#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
#define TCP_PUSH_BIT 0x10
/*
* "state" data for each active tcp conversation on the wire. This is
* basically a copy of the entire IP/TCP header from the last packet
* we saw from the conversation together with a small identifier
* the transmit & receive ends of the line use to locate saved header.
*/
struct cstate {
struct cstate *cs_next; /* next most recently used state (xmit only) */
u_short cs_hlen; /* size of hdr (receive only) */
u_char cs_id; /* connection # associated with this state */
u_char cs_filler;
union {
char csu_hdr[MAX_HDR];
struct ip csu_ip; /* ip/tcp hdr from most recent packet */
} vjcs_u;
};
#define cs_ip vjcs_u.csu_ip
#define cs_hdr vjcs_u.csu_hdr
/*
* all the state data for one serial line (we need one of these per line).
*/
struct vjcompress {
struct cstate *last_cs; /* most recently used tstate */
u_char last_recv; /* last rcvd conn. id */
u_char last_xmit; /* last sent conn. id */
u_short flags;
#ifndef VJ_NO_STATS
struct vjstat stats;
#endif
struct cstate tstate[MAX_STATES]; /* xmit connection states */
struct cstate rstate[MAX_STATES]; /* receive connection states */
};
/* flag values */
#define VJF_TOSS 1 /* tossing rcvd frames because of input err */
extern void vj_compress_init __P((struct vjcompress *comp, int max_state));
extern u_int vj_compress_tcp __P((struct ip *ip, u_int mlen,
struct vjcompress *comp, int compress_cid_flag,
u_char **vjhdrp));
extern void vj_uncompress_err __P((struct vjcompress *comp));
extern int vj_uncompress_uncomp __P((u_char *buf, int buflen,
struct vjcompress *comp));
extern int vj_uncompress_tcp __P((u_char *buf, int buflen, int total_len,
struct vjcompress *comp, u_char **hdrp,
u_int *hlenp));
#endif /* _VJCOMPRESS_H_ */

66
linux/Makefile.top Normal file
View File

@ -0,0 +1,66 @@
# PPP top-level Makefile for Linux.
DESTDIR = $(INSTROOT)@DESTDIR@
BINDIR = $(DESTDIR)/sbin
INCDIR = $(DESTDIR)/include
MANDIR = $(DESTDIR)/share/man
ETCDIR = $(INSTROOT)@SYSCONF@/ppp
# uid 0 = root
INSTALL= install
all:
cd chat; $(MAKE) $(MFLAGS) all
cd pppd/plugins; $(MAKE) $(MFLAGS) all
cd pppd; $(MAKE) $(MFLAGS) all
cd pppstats; $(MAKE) $(MFLAGS) all
cd pppdump; $(MAKE) $(MFLAGS) all
install: $(BINDIR) $(MANDIR)/man8 install-progs install-devel
install-progs:
cd chat; $(MAKE) $(MFLAGS) install
cd pppd/plugins; $(MAKE) $(MFLAGS) install
cd pppd; $(MAKE) $(MFLAGS) install
cd pppstats; $(MAKE) $(MFLAGS) install
cd pppdump; $(MAKE) $(MFLAGS) install
install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
$(ETCDIR)/chap-secrets
install-devel:
cd pppd; $(MAKE) $(MFLAGS) install-devel
$(ETCDIR)/options:
$(INSTALL) -c -m 644 etc.ppp/options $@
$(ETCDIR)/pap-secrets:
$(INSTALL) -c -m 600 etc.ppp/pap-secrets $@
$(ETCDIR)/chap-secrets:
$(INSTALL) -c -m 600 etc.ppp/chap-secrets $@
$(BINDIR):
$(INSTALL) -d -m 755 $@
$(MANDIR)/man8:
$(INSTALL) -d -m 755 $@
$(ETCDIR):
$(INSTALL) -d -m 755 $@
clean:
rm -f `find . -name '*.[oas]' -print`
rm -f `find . -name 'core' -print`
rm -f `find . -name '*~' -print`
cd chat; $(MAKE) clean
cd pppd/plugins; $(MAKE) clean
cd pppd; $(MAKE) clean
cd pppstats; $(MAKE) clean
cd pppdump; $(MAKE) clean
dist-clean: clean
rm -f Makefile `find . -name Makefile -print`
#kernel:
# cd linux; ./kinstall.sh
# no tests yet, one day...
installcheck:
true

1120
modules/bsd-comp.c Normal file

File diff suppressed because it is too large Load Diff

772
modules/deflate.c Normal file
View File

@ -0,0 +1,772 @@
/*
* ppp_deflate.c - interface the zlib procedures for Deflate compression
* and decompression (as used by gzip) to the PPP code.
* This version is for use with STREAMS under SunOS 4.x, Solaris 2,
* SVR4, OSF/1 and AIX 4.x.
*
* Copyright (c) 1994 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: deflate.c,v 1.12 2004/01/17 05:47:55 carlsonj Exp $
*/
#ifdef AIX4
#include <net/net_globals.h>
#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stream.h>
#include <net/ppp_defs.h>
#include "ppp_mod.h"
#define PACKETPTR mblk_t *
#include <net/ppp-comp.h>
#ifdef __osf__
#include "zlib.h"
#else
#include "../common/zlib.h"
#endif
#ifdef SOL2
#include <sys/sunddi.h>
#endif
#if DO_DEFLATE
#define DEFLATE_DEBUG 1
/*
* State for a Deflate (de)compressor.
*/
struct deflate_state {
int seqno;
int w_size;
int unit;
int hdrlen;
int mru;
int debug;
z_stream strm;
struct compstat stats;
};
#define DEFLATE_OVHD 2 /* Deflate overhead/packet */
static void *z_alloc __P((void *, u_int items, u_int size));
static void *z_alloc_init __P((void *, u_int items, u_int size));
static void z_free __P((void *, void *ptr));
static void *z_comp_alloc __P((u_char *options, int opt_len));
static void *z_decomp_alloc __P((u_char *options, int opt_len));
static void z_comp_free __P((void *state));
static void z_decomp_free __P((void *state));
static int z_comp_init __P((void *state, u_char *options, int opt_len,
int unit, int hdrlen, int debug));
static int z_decomp_init __P((void *state, u_char *options, int opt_len,
int unit, int hdrlen, int mru, int debug));
static int z_compress __P((void *state, mblk_t **mret,
mblk_t *mp, int slen, int maxolen));
static void z_incomp __P((void *state, mblk_t *dmsg));
static int z_decompress __P((void *state, mblk_t *cmp,
mblk_t **dmpp));
static void z_comp_reset __P((void *state));
static void z_decomp_reset __P((void *state));
static void z_comp_stats __P((void *state, struct compstat *stats));
/*
* Procedures exported to ppp_comp.c.
*/
struct compressor ppp_deflate = {
CI_DEFLATE, /* compress_proto */
z_comp_alloc, /* comp_alloc */
z_comp_free, /* comp_free */
z_comp_init, /* comp_init */
z_comp_reset, /* comp_reset */
z_compress, /* compress */
z_comp_stats, /* comp_stat */
z_decomp_alloc, /* decomp_alloc */
z_decomp_free, /* decomp_free */
z_decomp_init, /* decomp_init */
z_decomp_reset, /* decomp_reset */
z_decompress, /* decompress */
z_incomp, /* incomp */
z_comp_stats, /* decomp_stat */
};
struct compressor ppp_deflate_draft = {
CI_DEFLATE_DRAFT, /* compress_proto */
z_comp_alloc, /* comp_alloc */
z_comp_free, /* comp_free */
z_comp_init, /* comp_init */
z_comp_reset, /* comp_reset */
z_compress, /* compress */
z_comp_stats, /* comp_stat */
z_decomp_alloc, /* decomp_alloc */
z_decomp_free, /* decomp_free */
z_decomp_init, /* decomp_init */
z_decomp_reset, /* decomp_reset */
z_decompress, /* decompress */
z_incomp, /* incomp */
z_comp_stats, /* decomp_stat */
};
#define DECOMP_CHUNK 512
/*
* Space allocation and freeing routines for use by zlib routines.
*/
struct zchunk {
u_int size;
u_int guard;
};
#define GUARD_MAGIC 0x77a6011a
static void *
z_alloc_init(notused, items, size)
void *notused;
u_int items, size;
{
struct zchunk *z;
size = items * size + sizeof(struct zchunk);
#ifdef __osf__
z = (struct zchunk *) ALLOC_SLEEP(size);
#else
z = (struct zchunk *) ALLOC_NOSLEEP(size);
#endif
z->size = size;
z->guard = GUARD_MAGIC;
return (void *) (z + 1);
}
static void *
z_alloc(notused, items, size)
void *notused;
u_int items, size;
{
struct zchunk *z;
size = items * size + sizeof(struct zchunk);
z = (struct zchunk *) ALLOC_NOSLEEP(size);
z->size = size;
z->guard = GUARD_MAGIC;
return (void *) (z + 1);
}
static void
z_free(notused, ptr)
void *notused;
void *ptr;
{
struct zchunk *z = ((struct zchunk *) ptr) - 1;
if (z->guard != GUARD_MAGIC) {
printf("ppp: z_free of corrupted chunk at %x (%x, %x)\n",
z, z->size, z->guard);
return;
}
FREE(z, z->size);
}
/*
* Allocate space for a compressor.
*/
static void *
z_comp_alloc(options, opt_len)
u_char *options;
int opt_len;
{
struct deflate_state *state;
int w_size;
if (opt_len != CILEN_DEFLATE
|| (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| options[3] != DEFLATE_CHK_SEQUENCE)
return NULL;
w_size = DEFLATE_SIZE(options[2]);
/*
* N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
* 8 will cause kernel crashes because of a bug in zlib.
*/
if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
return NULL;
#ifdef __osf__
state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
#else
state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
#endif
if (state == NULL)
return NULL;
state->strm.next_in = NULL;
state->strm.zalloc = (alloc_func) z_alloc_init;
state->strm.zfree = (free_func) z_free;
if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
-w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
FREE(state, sizeof(*state));
return NULL;
}
state->strm.zalloc = (alloc_func) z_alloc;
state->w_size = w_size;
bzero(&state->stats, sizeof(state->stats));
return (void *) state;
}
static void
z_comp_free(arg)
void *arg;
{
struct deflate_state *state = (struct deflate_state *) arg;
deflateEnd(&state->strm);
FREE(state, sizeof(*state));
}
static int
z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
void *arg;
u_char *options;
int opt_len, unit, hdrlen, debug;
{
struct deflate_state *state = (struct deflate_state *) arg;
if (opt_len < CILEN_DEFLATE
|| (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| DEFLATE_SIZE(options[2]) != state->w_size
|| options[3] != DEFLATE_CHK_SEQUENCE)
return 0;
state->seqno = 0;
state->unit = unit;
state->hdrlen = hdrlen;
state->debug = debug;
deflateReset(&state->strm);
return 1;
}
static void
z_comp_reset(arg)
void *arg;
{
struct deflate_state *state = (struct deflate_state *) arg;
state->seqno = 0;
deflateReset(&state->strm);
}
static int
z_compress(arg, mret, mp, orig_len, maxolen)
void *arg;
mblk_t **mret; /* compressed packet (out) */
mblk_t *mp; /* uncompressed packet (in) */
int orig_len, maxolen;
{
struct deflate_state *state = (struct deflate_state *) arg;
u_char *rptr, *wptr;
int proto, olen, wspace, r, flush;
mblk_t *m;
/*
* Check that the protocol is in the range we handle.
*/
*mret = NULL;
rptr = mp->b_rptr;
if (rptr + PPP_HDRLEN > mp->b_wptr) {
if (!pullupmsg(mp, PPP_HDRLEN))
return 0;
rptr = mp->b_rptr;
}
proto = PPP_PROTOCOL(rptr);
if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
return orig_len;
/* Allocate one mblk initially. */
if (maxolen > orig_len)
maxolen = orig_len;
if (maxolen <= PPP_HDRLEN + 2) {
wspace = 0;
m = NULL;
} else {
wspace = maxolen + state->hdrlen;
if (wspace > 4096)
wspace = 4096;
m = allocb(wspace, BPRI_MED);
}
if (m != NULL) {
*mret = m;
if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
m->b_rptr += state->hdrlen;
m->b_wptr = m->b_rptr;
wspace -= state->hdrlen;
}
wptr = m->b_wptr;
/*
* Copy over the PPP header and store the 2-byte sequence number.
*/
wptr[0] = PPP_ADDRESS(rptr);
wptr[1] = PPP_CONTROL(rptr);
wptr[2] = PPP_COMP >> 8;
wptr[3] = PPP_COMP;
wptr += PPP_HDRLEN;
wptr[0] = state->seqno >> 8;
wptr[1] = state->seqno;
wptr += 2;
state->strm.next_out = wptr;
state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
} else {
state->strm.next_out = NULL;
state->strm.avail_out = 1000000;
}
++state->seqno;
rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */
state->strm.next_in = rptr;
state->strm.avail_in = mp->b_wptr - rptr;
mp = mp->b_cont;
flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
olen = 0;
for (;;) {
r = deflate(&state->strm, flush);
if (r != Z_OK) {
printf("z_compress: deflate returned %d (%s)\n",
r, (state->strm.msg? state->strm.msg: ""));
break;
}
if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
break; /* all done */
if (state->strm.avail_in == 0 && mp != NULL) {
state->strm.next_in = mp->b_rptr;
state->strm.avail_in = mp->b_wptr - mp->b_rptr;
mp = mp->b_cont;
if (mp == NULL)
flush = Z_PACKET_FLUSH;
}
if (state->strm.avail_out == 0) {
if (m != NULL) {
m->b_wptr += wspace;
olen += wspace;
wspace = maxolen - olen;
if (wspace <= 0) {
wspace = 0;
m->b_cont = NULL;
} else {
if (wspace < 32)
wspace = 32;
else if (wspace > 4096)
wspace = 4096;
m->b_cont = allocb(wspace, BPRI_MED);
}
m = m->b_cont;
if (m != NULL) {
state->strm.next_out = m->b_wptr;
state->strm.avail_out = wspace;
}
}
if (m == NULL) {
state->strm.next_out = NULL;
state->strm.avail_out = 1000000;
}
}
}
if (m != NULL) {
m->b_wptr += wspace - state->strm.avail_out;
olen += wspace - state->strm.avail_out;
}
/*
* See if we managed to reduce the size of the packet.
*/
if (olen < orig_len && m != NULL) {
state->stats.comp_bytes += olen;
state->stats.comp_packets++;
} else {
if (*mret != NULL) {
freemsg(*mret);
*mret = NULL;
}
state->stats.inc_bytes += orig_len;
state->stats.inc_packets++;
olen = orig_len;
}
state->stats.unc_bytes += orig_len;
state->stats.unc_packets++;
return olen;
}
static void
z_comp_stats(arg, stats)
void *arg;
struct compstat *stats;
{
struct deflate_state *state = (struct deflate_state *) arg;
u_int out;
*stats = state->stats;
stats->ratio = stats->unc_bytes;
out = stats->comp_bytes + stats->unc_bytes;
if (stats->ratio <= 0x7ffffff)
stats->ratio <<= 8;
else
out >>= 8;
if (out != 0)
stats->ratio /= out;
}
/*
* Allocate space for a decompressor.
*/
static void *
z_decomp_alloc(options, opt_len)
u_char *options;
int opt_len;
{
struct deflate_state *state;
int w_size;
if (opt_len != CILEN_DEFLATE
|| (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| options[3] != DEFLATE_CHK_SEQUENCE)
return NULL;
w_size = DEFLATE_SIZE(options[2]);
/*
* N.B. the 9 below should be DEFLATE_MIN_SIZE (8), but using
* 8 will cause kernel crashes because of a bug in zlib.
*/
if (w_size < 9 || w_size > DEFLATE_MAX_SIZE)
return NULL;
#ifdef __osf__
state = (struct deflate_state *) ALLOC_SLEEP(sizeof(*state));
#else
state = (struct deflate_state *) ALLOC_NOSLEEP(sizeof(*state));
#endif
if (state == NULL)
return NULL;
state->strm.next_out = NULL;
state->strm.zalloc = (alloc_func) z_alloc_init;
state->strm.zfree = (free_func) z_free;
if (inflateInit2(&state->strm, -w_size) != Z_OK) {
FREE(state, sizeof(*state));
return NULL;
}
state->strm.zalloc = (alloc_func) z_alloc;
state->w_size = w_size;
bzero(&state->stats, sizeof(state->stats));
return (void *) state;
}
static void
z_decomp_free(arg)
void *arg;
{
struct deflate_state *state = (struct deflate_state *) arg;
inflateEnd(&state->strm);
FREE(state, sizeof(*state));
}
static int
z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
void *arg;
u_char *options;
int opt_len, unit, hdrlen, mru, debug;
{
struct deflate_state *state = (struct deflate_state *) arg;
if (opt_len < CILEN_DEFLATE
|| (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
|| options[1] != CILEN_DEFLATE
|| DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
|| DEFLATE_SIZE(options[2]) != state->w_size
|| options[3] != DEFLATE_CHK_SEQUENCE)
return 0;
state->seqno = 0;
state->unit = unit;
state->hdrlen = hdrlen;
state->debug = debug;
state->mru = mru;
inflateReset(&state->strm);
return 1;
}
static void
z_decomp_reset(arg)
void *arg;
{
struct deflate_state *state = (struct deflate_state *) arg;
state->seqno = 0;
inflateReset(&state->strm);
}
/*
* Decompress a Deflate-compressed packet.
*
* Because of patent problems, we return DECOMP_ERROR for errors
* found by inspecting the input data and for system problems, but
* DECOMP_FATALERROR for any errors which could possibly be said to
* be being detected "after" decompression. For DECOMP_ERROR,
* we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
* infringing a patent of Motorola's if we do, so we take CCP down
* instead.
*
* Given that the frame has the correct sequence number and a good FCS,
* errors such as invalid codes in the input most likely indicate a
* bug, so we return DECOMP_FATALERROR for them in order to turn off
* compression, even though they are detected by inspecting the input.
*/
static int
z_decompress(arg, mi, mop)
void *arg;
mblk_t *mi, **mop;
{
struct deflate_state *state = (struct deflate_state *) arg;
mblk_t *mo, *mo_head;
u_char *rptr, *wptr;
int rlen, olen, ospace;
int seq, i, flush, r, decode_proto;
u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
*mop = NULL;
rptr = mi->b_rptr;
for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
while (rptr >= mi->b_wptr) {
mi = mi->b_cont;
if (mi == NULL)
return DECOMP_ERROR;
rptr = mi->b_rptr;
}
hdr[i] = *rptr++;
}
/* Check the sequence number. */
seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
if (seq != state->seqno) {
#if !DEFLATE_DEBUG
if (state->debug)
#endif
printf("z_decompress%d: bad seq # %d, expected %d\n",
state->unit, seq, state->seqno);
return DECOMP_ERROR;
}
++state->seqno;
/* Allocate an output message block. */
mo = allocb(DECOMP_CHUNK + state->hdrlen, BPRI_MED);
if (mo == NULL)
return DECOMP_ERROR;
mo_head = mo;
mo->b_cont = NULL;
mo->b_rptr += state->hdrlen;
mo->b_wptr = wptr = mo->b_rptr;
ospace = DECOMP_CHUNK;
olen = 0;
/*
* Fill in the first part of the PPP header. The protocol field
* comes from the decompressed data.
*/
wptr[0] = PPP_ADDRESS(hdr);
wptr[1] = PPP_CONTROL(hdr);
wptr[2] = 0;
/*
* Set up to call inflate. We set avail_out to 1 initially so we can
* look at the first byte of the output and decide whether we have
* a 1-byte or 2-byte protocol field.
*/
state->strm.next_in = rptr;
state->strm.avail_in = mi->b_wptr - rptr;
mi = mi->b_cont;
flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
rlen = state->strm.avail_in + PPP_HDRLEN + DEFLATE_OVHD;
state->strm.next_out = wptr + 3;
state->strm.avail_out = 1;
decode_proto = 1;
/*
* Call inflate, supplying more input or output as needed.
*/
for (;;) {
r = inflate(&state->strm, flush);
if (r != Z_OK) {
#if !DEFLATE_DEBUG
if (state->debug)
#endif
printf("z_decompress%d: inflate returned %d (%s)\n",
state->unit, r, (state->strm.msg? state->strm.msg: ""));
freemsg(mo_head);
return DECOMP_FATALERROR;
}
if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
break; /* all done */
if (state->strm.avail_in == 0 && mi != NULL) {
state->strm.next_in = mi->b_rptr;
state->strm.avail_in = mi->b_wptr - mi->b_rptr;
rlen += state->strm.avail_in;
mi = mi->b_cont;
if (mi == NULL)
flush = Z_PACKET_FLUSH;
}
if (state->strm.avail_out == 0) {
if (decode_proto) {
state->strm.avail_out = ospace - PPP_HDRLEN;
if ((wptr[3] & 1) == 0) {
/* 2-byte protocol field */
wptr[2] = wptr[3];
--state->strm.next_out;
++state->strm.avail_out;
}
decode_proto = 0;
} else {
mo->b_wptr += ospace;
olen += ospace;
mo->b_cont = allocb(DECOMP_CHUNK, BPRI_MED);
mo = mo->b_cont;
if (mo == NULL) {
freemsg(mo_head);
return DECOMP_ERROR;
}
state->strm.next_out = mo->b_rptr;
state->strm.avail_out = ospace = DECOMP_CHUNK;
}
}
}
if (decode_proto) {
freemsg(mo_head);
return DECOMP_ERROR;
}
mo->b_wptr += ospace - state->strm.avail_out;
olen += ospace - state->strm.avail_out;
#if DEFLATE_DEBUG
if (olen > state->mru + PPP_HDRLEN)
printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
state->unit, olen, state->mru + PPP_HDRLEN);
#endif
state->stats.unc_bytes += olen;
state->stats.unc_packets++;
state->stats.comp_bytes += rlen;
state->stats.comp_packets++;
*mop = mo_head;
return DECOMP_OK;
}
/*
* Incompressible data has arrived - add it to the history.
*/
static void
z_incomp(arg, mi)
void *arg;
mblk_t *mi;
{
struct deflate_state *state = (struct deflate_state *) arg;
u_char *rptr;
int rlen, proto, r;
/*
* Check that the protocol is one we handle.
*/
rptr = mi->b_rptr;
if (rptr + PPP_HDRLEN > mi->b_wptr) {
if (!pullupmsg(mi, PPP_HDRLEN))
return;
rptr = mi->b_rptr;
}
proto = PPP_PROTOCOL(rptr);
if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
return;
++state->seqno;
/*
* Iterate through the message blocks, adding the characters in them
* to the decompressor's history. For the first block, we start
* at the either the 1st or 2nd byte of the protocol field,
* depending on whether the protocol value is compressible.
*/
rlen = mi->b_wptr - mi->b_rptr;
state->strm.next_in = rptr + 3;
state->strm.avail_in = rlen - 3;
if (proto > 0xff) {
--state->strm.next_in;
++state->strm.avail_in;
}
for (;;) {
r = inflateIncomp(&state->strm);
if (r != Z_OK) {
/* gak! */
#if !DEFLATE_DEBUG
if (state->debug)
#endif
printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
state->unit, r, (state->strm.msg? state->strm.msg: ""));
return;
}
mi = mi->b_cont;
if (mi == NULL)
break;
state->strm.next_in = mi->b_rptr;
state->strm.avail_in = mi->b_wptr - mi->b_rptr;
rlen += state->strm.avail_in;
}
/*
* Update stats.
*/
state->stats.inc_bytes += rlen;
state->stats.inc_packets++;
state->stats.unc_bytes += rlen;
state->stats.unc_packets++;
}
#endif /* DO_DEFLATE */

873
modules/if_ppp.c Normal file
View File

@ -0,0 +1,873 @@
/*
* if_ppp.c - a network interface connected to a STREAMS module.
*
* Copyright (c) 1994 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: if_ppp.c,v 1.18 2002/12/06 09:49:15 paulus Exp $
*/
/*
* This file is used under SunOS 4 and Digital UNIX.
*
* This file provides the glue between PPP and IP.
*/
#define INET 1
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/netisr.h>
#include <net/ppp_defs.h>
#include <net/pppio.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#ifdef __osf__
#include <sys/ioctl.h>
#include <net/if_types.h>
#else
#include <sys/sockio.h>
#endif
#include "ppp_mod.h"
#include <sys/stream.h>
#ifdef SNIT_SUPPORT
#include <sys/time.h>
#include <net/nit_if.h>
#include <netinet/if_ether.h>
#endif
#ifdef __osf__
#define SIOCSIFMTU SIOCSIPMTU
#define SIOCGIFMTU SIOCRIPMTU
#define IFA_ADDR(ifa) (*(ifa)->ifa_addr)
#else
#define IFA_ADDR(ifa) ((ifa)->ifa_addr)
#endif
#define ifr_mtu ifr_metric
static int if_ppp_open __P((queue_t *, int, int, int));
static int if_ppp_close __P((queue_t *, int));
static int if_ppp_wput __P((queue_t *, mblk_t *));
static int if_ppp_rput __P((queue_t *, mblk_t *));
#define PPP_IF_ID 0x8021
static struct module_info minfo = {
PPP_IF_ID, "if_ppp", 0, INFPSZ, 4096, 128
};
static struct qinit rinit = {
if_ppp_rput, NULL, if_ppp_open, if_ppp_close, NULL, &minfo, NULL
};
static struct qinit winit = {
if_ppp_wput, NULL, NULL, NULL, NULL, &minfo, NULL
};
struct streamtab if_pppinfo = {
&rinit, &winit, NULL, NULL
};
typedef struct if_ppp_state {
int unit;
queue_t *q;
int flags;
} if_ppp_t;
/* Values for flags */
#define DBGLOG 1
static int if_ppp_count; /* Number of currently-active streams */
static int ppp_nalloc; /* Number of elements of ifs and states */
static struct ifnet **ifs; /* Array of pointers to interface structs */
static if_ppp_t **states; /* Array of pointers to state structs */
static int if_ppp_output __P((struct ifnet *, struct mbuf *,
struct sockaddr *));
static int if_ppp_ioctl __P((struct ifnet *, u_int, caddr_t));
static struct mbuf *make_mbufs __P((mblk_t *, int));
static mblk_t *make_message __P((struct mbuf *, int));
#ifdef SNIT_SUPPORT
/* Fake ether header for SNIT */
static struct ether_header snit_ehdr = {{0}, {0}, ETHERTYPE_IP};
#endif
#ifndef __osf__
static void ppp_if_detach __P((struct ifnet *));
/*
* Detach all the interfaces before unloading.
* Not sure this works.
*/
int
if_ppp_unload()
{
int i;
if (if_ppp_count > 0)
return EBUSY;
for (i = 0; i < ppp_nalloc; ++i)
if (ifs[i] != 0)
ppp_if_detach(ifs[i]);
if (ifs) {
FREE(ifs, ppp_nalloc * sizeof (struct ifnet *));
FREE(states, ppp_nalloc * sizeof (struct if_ppp_t *));
}
ppp_nalloc = 0;
return 0;
}
#endif /* __osf__ */
/*
* STREAMS module entry points.
*/
static int
if_ppp_open(q, dev, flag, sflag)
queue_t *q;
int dev;
int flag, sflag;
{
if_ppp_t *sp;
if (q->q_ptr == 0) {
sp = (if_ppp_t *) ALLOC_SLEEP(sizeof (if_ppp_t));
if (sp == 0)
return OPENFAIL;
bzero(sp, sizeof (if_ppp_t));
q->q_ptr = (caddr_t) sp;
WR(q)->q_ptr = (caddr_t) sp;
sp->unit = -1; /* no interface unit attached at present */
sp->q = WR(q);
sp->flags = 0;
++if_ppp_count;
}
return 0;
}
static int
if_ppp_close(q, flag)
queue_t *q;
int flag;
{
if_ppp_t *sp;
struct ifnet *ifp;
sp = (if_ppp_t *) q->q_ptr;
if (sp != 0) {
if (sp->flags & DBGLOG)
printf("if_ppp closed, q=%x sp=%x\n", q, sp);
if (sp->unit >= 0) {
if (sp->unit < ppp_nalloc) {
states[sp->unit] = 0;
ifp = ifs[sp->unit];
if (ifp != 0)
ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
#ifdef DEBUG
} else {
printf("if_ppp: unit %d nonexistent!\n", sp->unit);
#endif
}
}
FREE(sp, sizeof (if_ppp_t));
--if_ppp_count;
}
return 0;
}
static int
if_ppp_wput(q, mp)
queue_t *q;
mblk_t *mp;
{
if_ppp_t *sp;
struct iocblk *iop;
int error, unit;
struct ifnet *ifp;
sp = (if_ppp_t *) q->q_ptr;
switch (mp->b_datap->db_type) {
case M_DATA:
/*
* Now why would we be getting data coming in here??
*/
if (sp->flags & DBGLOG)
printf("if_ppp: got M_DATA len=%d\n", msgdsize(mp));
freemsg(mp);
break;
case M_IOCTL:
iop = (struct iocblk *) mp->b_rptr;
error = EINVAL;
if (sp->flags & DBGLOG)
printf("if_ppp: got ioctl cmd=%x count=%d\n",
iop->ioc_cmd, iop->ioc_count);
switch (iop->ioc_cmd) {
case PPPIO_NEWPPA: /* well almost */
if (iop->ioc_count != sizeof(int) || sp->unit >= 0)
break;
if ((error = NOTSUSER()) != 0)
break;
unit = *(int *)mp->b_cont->b_rptr;
/* Check that this unit isn't already in use */
if (unit < ppp_nalloc && states[unit] != 0) {
error = EADDRINUSE;
break;
}
/* Extend ifs and states arrays if necessary. */
error = ENOSR;
if (unit >= ppp_nalloc) {
int newn;
struct ifnet **newifs;
if_ppp_t **newstates;
newn = unit + 4;
if (sp->flags & DBGLOG)
printf("if_ppp: extending ifs to %d\n", newn);
newifs = (struct ifnet **)
ALLOC_NOSLEEP(newn * sizeof (struct ifnet *));
if (newifs == 0)
break;
bzero(newifs, newn * sizeof (struct ifnet *));
newstates = (if_ppp_t **)
ALLOC_NOSLEEP(newn * sizeof (struct if_ppp_t *));
if (newstates == 0) {
FREE(newifs, newn * sizeof (struct ifnet *));
break;
}
bzero(newstates, newn * sizeof (struct if_ppp_t *));
bcopy(ifs, newifs, ppp_nalloc * sizeof(struct ifnet *));
bcopy(states, newstates, ppp_nalloc * sizeof(if_ppp_t *));
if (ifs) {
FREE(ifs, ppp_nalloc * sizeof(struct ifnet *));
FREE(states, ppp_nalloc * sizeof(if_ppp_t *));
}
ifs = newifs;
states = newstates;
ppp_nalloc = newn;
}
/* Allocate a new ifnet struct if necessary. */
ifp = ifs[unit];
if (ifp == 0) {
ifp = (struct ifnet *) ALLOC_NOSLEEP(sizeof (struct ifnet));
if (ifp == 0)
break;
bzero(ifp, sizeof (struct ifnet));
ifs[unit] = ifp;
ifp->if_name = "ppp";
ifp->if_unit = unit;
ifp->if_mtu = PPP_MTU;
ifp->if_flags = IFF_POINTOPOINT | IFF_RUNNING;
#ifndef __osf__
#ifdef IFF_MULTICAST
ifp->if_flags |= IFF_MULTICAST;
#endif
#endif /* __osf__ */
ifp->if_output = if_ppp_output;
#ifdef __osf__
ifp->if_version = "Point-to-Point Protocol, version 2.3.11";
ifp->if_mediamtu = PPP_MTU;
ifp->if_type = IFT_PPP;
ifp->if_hdrlen = PPP_HDRLEN;
ifp->if_addrlen = 0;
ifp->if_flags |= IFF_NOARP | IFF_SIMPLEX | IFF_NOTRAILERS;
#ifdef IFF_VAR_MTU
ifp->if_flags |= IFF_VAR_MTU;
#endif
#ifdef NETMASTERCPU
ifp->if_affinity = NETMASTERCPU;
#endif
#endif
ifp->if_ioctl = if_ppp_ioctl;
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
if_attach(ifp);
if (sp->flags & DBGLOG)
printf("if_ppp: created unit %d\n", unit);
} else {
ifp->if_mtu = PPP_MTU;
ifp->if_flags |= IFF_RUNNING;
}
states[unit] = sp;
sp->unit = unit;
error = 0;
iop->ioc_count = 0;
if (sp->flags & DBGLOG)
printf("if_ppp: attached unit %d, sp=%x q=%x\n", unit,
sp, sp->q);
break;
case PPPIO_DEBUG:
error = -1;
if (iop->ioc_count == sizeof(int)) {
if (*(int *)mp->b_cont->b_rptr == PPPDBG_LOG + PPPDBG_IF) {
printf("if_ppp: debug log enabled, q=%x sp=%x\n", q, sp);
sp->flags |= DBGLOG;
error = 0;
iop->ioc_count = 0;
}
}
break;
default:
error = -1;
break;
}
if (sp->flags & DBGLOG)
printf("if_ppp: ioctl result %d\n", error);
if (error < 0)
putnext(q, mp);
else if (error == 0) {
mp->b_datap->db_type = M_IOCACK;
qreply(q, mp);
} else {
mp->b_datap->db_type = M_IOCNAK;
iop->ioc_count = 0;
iop->ioc_error = error;
qreply(q, mp);
}
break;
default:
putnext(q, mp);
}
return 0;
}
static int
if_ppp_rput(q, mp)
queue_t *q;
mblk_t *mp;
{
if_ppp_t *sp;
int proto, s;
struct mbuf *mb;
struct ifqueue *inq;
struct ifnet *ifp;
int len;
sp = (if_ppp_t *) q->q_ptr;
switch (mp->b_datap->db_type) {
case M_DATA:
/*
* Convert the message into an mbuf chain
* and inject it into the network code.
*/
if (sp->flags & DBGLOG)
printf("if_ppp: rput pkt len %d data %x %x %x %x %x %x %x %x\n",
msgdsize(mp), mp->b_rptr[0], mp->b_rptr[1], mp->b_rptr[2],
mp->b_rptr[3], mp->b_rptr[4], mp->b_rptr[5], mp->b_rptr[6],
mp->b_rptr[7]);
if (sp->unit < 0) {
freemsg(mp);
break;
}
if (sp->unit >= ppp_nalloc || (ifp = ifs[sp->unit]) == 0) {
#ifdef DEBUG
printf("if_ppp: no unit %d!\n", sp->unit);
#endif
freemsg(mp);
break;
}
if ((ifp->if_flags & IFF_UP) == 0) {
freemsg(mp);
break;
}
++ifp->if_ipackets;
proto = PPP_PROTOCOL(mp->b_rptr);
adjmsg(mp, PPP_HDRLEN);
len = msgdsize(mp);
mb = make_mbufs(mp, sizeof(struct ifnet *));
freemsg(mp);
if (mb == NULL) {
if (sp->flags & DBGLOG)
printf("if_ppp%d: make_mbufs failed\n", ifp->if_unit);
++ifp->if_ierrors;
break;
}
#ifdef SNIT_SUPPORT
if (proto == PPP_IP && (ifp->if_flags & IFF_PROMISC)) {
struct nit_if nif;
nif.nif_header = (caddr_t) &snit_ehdr;
nif.nif_hdrlen = sizeof(snit_ehdr);
nif.nif_bodylen = len;
nif.nif_promisc = 0;
snit_intr(ifp, mb, &nif);
}
#endif
/*
* For Digital UNIX, there's space set aside in the header mbuf
* for the interface info.
*
* For Sun it's smuggled around via a pointer at the front of the mbuf.
*/
#ifdef __osf__
mb->m_pkthdr.rcvif = ifp;
mb->m_pkthdr.len = len;
#else
mb->m_off -= sizeof(struct ifnet *);
mb->m_len += sizeof(struct ifnet *);
*mtod(mb, struct ifnet **) = ifp;
#endif
inq = 0;
switch (proto) {
case PPP_IP:
inq = &ipintrq;
schednetisr(NETISR_IP);
}
if (inq != 0) {
s = splhigh();
if (IF_QFULL(inq)) {
IF_DROP(inq);
++ifp->if_ierrors;
if (sp->flags & DBGLOG)
printf("if_ppp: inq full, proto=%x\n", proto);
m_freem(mb);
} else {
IF_ENQUEUE(inq, mb);
}
splx(s);
} else {
if (sp->flags & DBGLOG)
printf("if_ppp%d: proto=%x?\n", ifp->if_unit, proto);
++ifp->if_ierrors;
m_freem(mb);
}
break;
default:
putnext(q, mp);
}
return 0;
}
/*
* Network code wants to output a packet.
* Turn it into a STREAMS message and send it down.
*/
static int
if_ppp_output(ifp, m0, dst)
struct ifnet *ifp;
struct mbuf *m0;
struct sockaddr *dst;
{
mblk_t *mp;
int proto, s;
if_ppp_t *sp;
u_char *p;
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m0);
return ENETDOWN;
}
if ((unsigned)ifp->if_unit >= ppp_nalloc) {
#ifdef DEBUG
printf("if_ppp_output: unit %d?\n", ifp->if_unit);
#endif
m_freem(m0);
return EINVAL;
}
sp = states[ifp->if_unit];
if (sp == 0) {
#ifdef DEBUG
printf("if_ppp_output: no queue?\n");
#endif
m_freem(m0);
return ENETDOWN;
}
if (sp->flags & DBGLOG) {
p = mtod(m0, u_char *);
printf("if_ppp_output%d: af=%d data=%x %x %x %x %x %x %x %x q=%x\n",
ifp->if_unit, dst->sa_family, p[0], p[1], p[2], p[3], p[4],
p[5], p[6], p[7], sp->q);
}
switch (dst->sa_family) {
case AF_INET:
proto = PPP_IP;
#ifdef SNIT_SUPPORT
if (ifp->if_flags & IFF_PROMISC) {
struct nit_if nif;
struct mbuf *m;
int len;
for (len = 0, m = m0; m != NULL; m = m->m_next)
len += m->m_len;
nif.nif_header = (caddr_t) &snit_ehdr;
nif.nif_hdrlen = sizeof(snit_ehdr);
nif.nif_bodylen = len;
nif.nif_promisc = 0;
snit_intr(ifp, m0, &nif);
}
#endif
break;
default:
m_freem(m0);
return EAFNOSUPPORT;
}
++ifp->if_opackets;
mp = make_message(m0, PPP_HDRLEN);
m_freem(m0);
if (mp == 0) {
++ifp->if_oerrors;
return ENOBUFS;
}
mp->b_rptr -= PPP_HDRLEN;
mp->b_rptr[0] = PPP_ALLSTATIONS;
mp->b_rptr[1] = PPP_UI;
mp->b_rptr[2] = proto >> 8;
mp->b_rptr[3] = proto;
s = splstr();
if (sp->flags & DBGLOG)
printf("if_ppp: putnext(%x, %x), r=%x w=%x p=%x\n",
sp->q, mp, mp->b_rptr, mp->b_wptr, proto);
putnext(sp->q, mp);
splx(s);
return 0;
}
/*
* Socket ioctl routine for ppp interfaces.
*/
static int
if_ppp_ioctl(ifp, cmd, data)
struct ifnet *ifp;
u_int cmd;
caddr_t data;
{
int s, error;
struct ifreq *ifr = (struct ifreq *) data;
struct ifaddr *ifa = (struct ifaddr *) data;
u_short mtu;
error = 0;
s = splimp();
switch (cmd) {
case SIOCSIFFLAGS:
if ((ifp->if_flags & IFF_RUNNING) == 0)
ifp->if_flags &= ~IFF_UP;
break;
case SIOCSIFADDR:
if (IFA_ADDR(ifa).sa_family != AF_INET)
error = EAFNOSUPPORT;
break;
case SIOCSIFDSTADDR:
if (IFA_ADDR(ifa).sa_family != AF_INET)
error = EAFNOSUPPORT;
break;
case SIOCSIFMTU:
if ((error = NOTSUSER()) != 0)
break;
#ifdef __osf__
/* this hack is necessary because ifioctl checks ifr_data
* in 4.0 and 5.0, but ifr_data and ifr_metric overlay each
* other in the definition of struct ifreq so pppd can't set both.
*/
bcopy(ifr->ifr_data, &mtu, sizeof (u_short));
ifr->ifr_mtu = mtu;
#endif
if (ifr->ifr_mtu < PPP_MINMTU || ifr->ifr_mtu > PPP_MAXMTU) {
error = EINVAL;
break;
}
ifp->if_mtu = ifr->ifr_mtu;
break;
case SIOCGIFMTU:
ifr->ifr_mtu = ifp->if_mtu;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
switch(ifr->ifr_addr.sa_family) {
case AF_INET:
break;
default:
error = EAFNOSUPPORT;
break;
}
break;
default:
error = EINVAL;
}
splx(s);
return (error);
}
/*
* Turn a STREAMS message into an mbuf chain.
*/
static struct mbuf *
make_mbufs(mp, off)
mblk_t *mp;
int off;
{
struct mbuf *head, **prevp, *m;
int len, space, n;
unsigned char *cp, *dp;
len = msgdsize(mp);
if (len == 0)
return 0;
prevp = &head;
space = 0;
cp = mp->b_rptr;
#ifdef __osf__
MGETHDR(m, M_DONTWAIT, MT_DATA);
m->m_len = 0;
space = MHLEN;
*prevp = m;
prevp = &m->m_next;
dp = mtod(m, unsigned char *);
len -= space;
off = 0;
#endif
for (;;) {
while (cp >= mp->b_wptr) {
mp = mp->b_cont;
if (mp == 0) {
*prevp = 0;
return head;
}
cp = mp->b_rptr;
}
n = mp->b_wptr - cp;
if (space == 0) {
MGET(m, M_DONTWAIT, MT_DATA);
*prevp = m;
if (m == 0) {
if (head != 0)
m_freem(head);
return 0;
}
if (len + off > 2 * MLEN) {
#ifdef __osf__
MCLGET(m, M_DONTWAIT);
#else
MCLGET(m);
#endif
}
#ifdef __osf__
space = ((m->m_flags & M_EXT) ? MCLBYTES : MLEN);
#else
space = (m->m_off > MMAXOFF? MCLBYTES: MLEN) - off;
m->m_off += off;
#endif
m->m_len = 0;
len -= space;
dp = mtod(m, unsigned char *);
off = 0;
prevp = &m->m_next;
}
if (n > space)
n = space;
bcopy(cp, dp, n);
cp += n;
dp += n;
space -= n;
m->m_len += n;
}
}
/*
* Turn an mbuf chain into a STREAMS message.
*/
#define ALLOCB_MAX 4096
static mblk_t *
make_message(m, off)
struct mbuf *m;
int off;
{
mblk_t *head, **prevp, *mp;
int len, space, n, nb;
unsigned char *cp, *dp;
struct mbuf *nm;
len = 0;
for (nm = m; nm != 0; nm = nm->m_next)
len += nm->m_len;
prevp = &head;
space = 0;
cp = mtod(m, unsigned char *);
nb = m->m_len;
for (;;) {
while (nb <= 0) {
m = m->m_next;
if (m == 0) {
*prevp = 0;
return head;
}
cp = mtod(m, unsigned char *);
nb = m->m_len;
}
if (space == 0) {
space = len + off;
if (space > ALLOCB_MAX)
space = ALLOCB_MAX;
mp = allocb(space, BPRI_LO);
*prevp = mp;
if (mp == 0) {
if (head != 0)
freemsg(head);
return 0;
}
dp = mp->b_rptr += off;
space -= off;
len -= space;
off = 0;
prevp = &mp->b_cont;
}
n = nb < space? nb: space;
bcopy(cp, dp, n);
cp += n;
dp += n;
nb -= n;
space -= n;
mp->b_wptr = dp;
}
}
/*
* Digital UNIX doesn't allow for removing ifnet structures
* from the list. But then we're not using this as a loadable
* module anyway, so that's OK.
*
* Under SunOS, this should allow the module to be unloaded.
* Unfortunately, it doesn't seem to detach all the references,
* so your system may well crash after you unload this module :-(
*/
#ifndef __osf__
/*
* Remove an interface from the system.
* This routine contains magic.
*/
#include <net/route.h>
#include <netinet/in_pcb.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
static void
ppp_if_detach(ifp)
struct ifnet *ifp;
{
int s;
struct inpcb *pcb;
struct ifaddr *ifa;
struct in_ifaddr **inap;
struct ifnet **ifpp;
s = splhigh();
/*
* Clear the interface from any routes currently cached in
* TCP or UDP protocol control blocks.
*/
for (pcb = tcb.inp_next; pcb != &tcb; pcb = pcb->inp_next)
if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
in_losing(pcb);
for (pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next)
if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
in_losing(pcb);
/*
* Delete routes through all addresses of the interface.
*/
for (ifa = ifp->if_addrlist; ifa != 0; ifa = ifa->ifa_next) {
rtinit(ifa, ifa, SIOCDELRT, RTF_HOST);
rtinit(ifa, ifa, SIOCDELRT, 0);
}
/*
* Unlink the interface's address(es) from the in_ifaddr list.
*/
for (inap = &in_ifaddr; *inap != 0; ) {
if ((*inap)->ia_ifa.ifa_ifp == ifp)
*inap = (*inap)->ia_next;
else
inap = &(*inap)->ia_next;
}
/*
* Delete the interface from the ifnet list.
*/
for (ifpp = &ifnet; (*ifpp) != 0; ) {
if (*ifpp == ifp)
break;
ifpp = &(*ifpp)->if_next;
}
if (*ifpp == 0)
printf("couldn't find interface ppp%d in ifnet list\n", ifp->if_unit);
else
*ifpp = ifp->if_next;
splx(s);
}
#endif /* __osf__ */

2494
modules/ppp.c Normal file

File diff suppressed because it is too large Load Diff

873
modules/ppp_ahdlc.c Normal file
View File

@ -0,0 +1,873 @@
/*
* ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
*
* Re-written by Adi Masputra <adi.masputra@sun.com>, based on
* the original ppp_ahdlc.c
*
* Copyright (c) 2000 by Sun Microsystems, Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, provided that the above copyright
* notice appears in all copies.
*
* SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
*
* Copyright (c) 1994 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
*
* $Id: ppp_ahdlc.c,v 1.18 2002/12/06 09:49:15 paulus Exp $
*/
/*
* This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stream.h>
#include <sys/errno.h>
#ifdef SVR4
#include <sys/conf.h>
#include <sys/kmem.h>
#include <sys/cmn_err.h>
#include <sys/ddi.h>
#else
#include <sys/user.h>
#ifdef __osf__
#include <sys/cmn_err.h>
#endif
#endif /* SVR4 */
#include <net/ppp_defs.h>
#include <net/pppio.h>
#include "ppp_mod.h"
/*
* Right now, mutex is only enabled for Solaris 2.x
*/
#if defined(SOL2)
#define USE_MUTEX
#endif /* SOL2 */
/*
* intpointer_t and uintpointer_t are signed and unsigned integer types
* large enough to hold any data pointer; that is, data pointers can be
* assigned into or from these integer types without losing precision.
* On recent Solaris releases, these types are defined in sys/int_types.h,
* but not on SunOS 4.x or the earlier Solaris versions.
*/
#if defined(_LP64) || defined(_I32LPx)
typedef long intpointer_t;
typedef unsigned long uintpointer_t;
#else
typedef int intpointer_t;
typedef unsigned int uintpointer_t;
#endif
MOD_OPEN_DECL(ahdlc_open);
MOD_CLOSE_DECL(ahdlc_close);
static int ahdlc_wput __P((queue_t *, mblk_t *));
static int ahdlc_rput __P((queue_t *, mblk_t *));
static void ahdlc_encode __P((queue_t *, mblk_t *));
static void ahdlc_decode __P((queue_t *, mblk_t *));
static int msg_byte __P((mblk_t *, unsigned int));
#if defined(SOL2)
/*
* Don't send HDLC start flag is last transmit is within 1.5 seconds -
* FLAG_TIME is defined is microseconds
*/
#define FLAG_TIME 1500
#define ABS(x) (x >= 0 ? x : (-x))
#endif /* SOL2 */
/*
* Extract byte i of message mp
*/
#define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
msg_byte((mp), (i)))
/*
* Is this LCP packet one we have to transmit using LCP defaults?
*/
#define LCP_USE_DFLT(mp) (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
/*
* Standard STREAMS declarations
*/
static struct module_info minfo = {
0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
};
static struct qinit rinit = {
ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
};
static struct qinit winit = {
ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
};
#if defined(SVR4) && !defined(SOL2)
int phdldevflag = 0;
#define ppp_ahdlcinfo phdlinfo
#endif /* defined(SVR4) && !defined(SOL2) */
struct streamtab ppp_ahdlcinfo = {
&rinit, /* ptr to st_rdinit */
&winit, /* ptr to st_wrinit */
NULL, /* ptr to st_muxrinit */
NULL, /* ptr to st_muxwinit */
#if defined(SUNOS4)
NULL /* ptr to ptr to st_modlist */
#endif /* SUNOS4 */
};
#if defined(SUNOS4)
int ppp_ahdlc_count = 0; /* open counter */
#endif /* SUNOS4 */
/*
* Per-stream state structure
*/
typedef struct ahdlc_state {
#if defined(USE_MUTEX)
kmutex_t lock; /* lock for this structure */
#endif /* USE_MUTEX */
int flags; /* link flags */
mblk_t *rx_buf; /* ptr to receive buffer */
int rx_buf_size; /* receive buffer size */
ushort_t infcs; /* calculated rx HDLC FCS */
u_int32_t xaccm[8]; /* 256-bit xmit ACCM */
u_int32_t raccm; /* 32-bit rcv ACCM */
int mtu; /* interface MTU */
int mru; /* link MRU */
int unit; /* current PPP unit number */
struct pppstat stats; /* statistic structure */
#if defined(SOL2)
clock_t flag_time; /* time in usec between flags */
clock_t lbolt; /* last updated lbolt */
#endif /* SOL2 */
} ahdlc_state_t;
/*
* Values for flags
*/
#define ESCAPED 0x100 /* last saw escape char on input */
#define IFLUSH 0x200 /* flushing input due to error */
/*
* RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
*/
#define RCV_FLAGS (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
/*
* FCS lookup table as calculated by genfcstab.
*/
static u_short fcstab[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
static u_int32_t paritytab[8] =
{
0x96696996, 0x69969669, 0x69969669, 0x96696996,
0x69969669, 0x96696996, 0x96696996, 0x69969669
};
/*
* STREAMS module open (entry) point
*/
MOD_OPEN(ahdlc_open)
{
ahdlc_state_t *state;
/*
* Return if it's already opened
*/
if (q->q_ptr) {
return 0;
}
/*
* This can only be opened as a module
*/
if (sflag != MODOPEN) {
return 0;
}
state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
if (state == 0)
OPEN_ERROR(ENOSR);
bzero((caddr_t) state, sizeof(ahdlc_state_t));
q->q_ptr = (caddr_t) state;
WR(q)->q_ptr = (caddr_t) state;
#if defined(USE_MUTEX)
mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
state->xaccm[0] = ~0; /* escape 0x00 through 0x1f */
state->xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
state->mru = PPP_MRU; /* default of 1500 bytes */
#if defined(SOL2)
state->flag_time = drv_usectohz(FLAG_TIME);
#endif /* SOL2 */
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
#if defined(SUNOS4)
ppp_ahdlc_count++;
#endif /* SUNOS4 */
qprocson(q);
return 0;
}
/*
* STREAMS module close (exit) point
*/
MOD_CLOSE(ahdlc_close)
{
ahdlc_state_t *state;
qprocsoff(q);
state = (ahdlc_state_t *) q->q_ptr;
if (state == 0) {
DPRINT("state == 0 in ahdlc_close\n");
return 0;
}
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
if (state->rx_buf != 0) {
freemsg(state->rx_buf);
state->rx_buf = 0;
}
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
mutex_destroy(&state->lock);
#endif /* USE_MUTEX */
FREE(q->q_ptr, sizeof(ahdlc_state_t));
q->q_ptr = NULL;
OTHERQ(q)->q_ptr = NULL;
#if defined(SUNOS4)
if (ppp_ahdlc_count)
ppp_ahdlc_count--;
#endif /* SUNOS4 */
return 0;
}
/*
* Write side put routine
*/
static int
ahdlc_wput(q, mp)
queue_t *q;
mblk_t *mp;
{
ahdlc_state_t *state;
struct iocblk *iop;
int error;
mblk_t *np;
struct ppp_stats *psp;
state = (ahdlc_state_t *) q->q_ptr;
if (state == 0) {
DPRINT("state == 0 in ahdlc_wput\n");
freemsg(mp);
return 0;
}
switch (mp->b_datap->db_type) {
case M_DATA:
/*
* A data packet - do character-stuffing and FCS, and
* send it onwards.
*/
ahdlc_encode(q, mp);
freemsg(mp);
break;
case M_IOCTL:
iop = (struct iocblk *) mp->b_rptr;
error = EINVAL;
switch (iop->ioc_cmd) {
case PPPIO_XACCM:
if ((iop->ioc_count < sizeof(u_int32_t)) ||
(iop->ioc_count > sizeof(ext_accm))) {
break;
}
if (mp->b_cont == 0) {
DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
break;
}
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
iop->ioc_count);
state->xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
state->xaccm[3] |= 0x60000000; /* do escape 0x7d, 0x7e */
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
iop->ioc_count = 0;
error = 0;
break;
case PPPIO_RACCM:
if (iop->ioc_count != sizeof(u_int32_t))
break;
if (mp->b_cont == 0) {
DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
break;
}
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
sizeof(u_int32_t));
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
iop->ioc_count = 0;
error = 0;
break;
case PPPIO_GCLEAN:
np = allocb(sizeof(int), BPRI_HI);
if (np == 0) {
error = ENOSR;
break;
}
if (mp->b_cont != 0)
freemsg(mp->b_cont);
mp->b_cont = np;
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
*(int *)np->b_wptr = state->flags & RCV_FLAGS;
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
np->b_wptr += sizeof(int);
iop->ioc_count = sizeof(int);
error = 0;
break;
case PPPIO_GETSTAT:
np = allocb(sizeof(struct ppp_stats), BPRI_HI);
if (np == 0) {
error = ENOSR;
break;
}
if (mp->b_cont != 0)
freemsg(mp->b_cont);
mp->b_cont = np;
psp = (struct ppp_stats *) np->b_wptr;
np->b_wptr += sizeof(struct ppp_stats);
bzero((caddr_t)psp, sizeof(struct ppp_stats));
psp->p = state->stats;
iop->ioc_count = sizeof(struct ppp_stats);
error = 0;
break;
case PPPIO_LASTMOD:
/* we knew this anyway */
error = 0;
break;
default:
error = -1;
break;
}
if (error < 0)
putnext(q, mp);
else if (error == 0) {
mp->b_datap->db_type = M_IOCACK;
qreply(q, mp);
} else {
mp->b_datap->db_type = M_IOCNAK;
iop->ioc_count = 0;
iop->ioc_error = error;
qreply(q, mp);
}
break;
case M_CTL:
switch (*mp->b_rptr) {
case PPPCTL_MTU:
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
state->mtu = ((unsigned short *)mp->b_rptr)[1];
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
freemsg(mp);
break;
case PPPCTL_MRU:
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
state->mru = ((unsigned short *)mp->b_rptr)[1];
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
freemsg(mp);
break;
case PPPCTL_UNIT:
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
state->unit = mp->b_rptr[1];
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
break;
default:
putnext(q, mp);
}
break;
default:
putnext(q, mp);
}
return 0;
}
/*
* Read side put routine
*/
static int
ahdlc_rput(q, mp)
queue_t *q;
mblk_t *mp;
{
ahdlc_state_t *state;
state = (ahdlc_state_t *) q->q_ptr;
if (state == 0) {
DPRINT("state == 0 in ahdlc_rput\n");
freemsg(mp);
return 0;
}
switch (mp->b_datap->db_type) {
case M_DATA:
ahdlc_decode(q, mp);
break;
case M_HANGUP:
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
if (state->rx_buf != 0) {
/* XXX would like to send this up for debugging */
freemsg(state->rx_buf);
state->rx_buf = 0;
}
state->flags = IFLUSH;
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
putnext(q, mp);
break;
default:
putnext(q, mp);
}
return 0;
}
/*
* Extract bit c from map m, to determine if c needs to be escaped
*/
#define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
static void
ahdlc_encode(q, mp)
queue_t *q;
mblk_t *mp;
{
ahdlc_state_t *state;
u_int32_t *xaccm, loc_xaccm[8];
ushort_t fcs;
size_t outmp_len;
mblk_t *outmp, *tmp;
uchar_t *dp, fcs_val;
int is_lcp, code;
#if defined(SOL2)
clock_t lbolt;
#endif /* SOL2 */
if (msgdsize(mp) < 4) {
return;
}
state = (ahdlc_state_t *)q->q_ptr;
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
/*
* Allocate an output buffer large enough to handle a case where all
* characters need to be escaped
*/
outmp_len = (msgdsize(mp) << 1) + /* input block x 2 */
(sizeof(fcs) << 2) + /* HDLC FCS x 4 */
(sizeof(uchar_t) << 1); /* HDLC flags x 2 */
outmp = allocb(outmp_len, BPRI_MED);
if (outmp == NULL) {
state->stats.ppp_oerrors++;
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
return;
}
#if defined(SOL2)
/*
* Check if our last transmit happenned within flag_time, using
* the system's LBOLT value in clock ticks
*/
if (drv_getparm(LBOLT, &lbolt) != -1) {
if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
*outmp->b_wptr++ = PPP_FLAG;
}
state->lbolt = lbolt;
} else {
*outmp->b_wptr++ = PPP_FLAG;
}
#else
/*
* If the driver below still has a message to process, skip the
* HDLC flag, otherwise, put one in the beginning
*/
if (qsize(q->q_next) == 0) {
*outmp->b_wptr++ = PPP_FLAG;
}
#endif
/*
* All control characters must be escaped for LCP packets with code
* values between 1 (Conf-Req) and 7 (Code-Rej).
*/
is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) &&
(MSG_BYTE(mp, 1) == PPP_UI) &&
(MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
(MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
LCP_USE_DFLT(mp));
xaccm = state->xaccm;
if (is_lcp) {
bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
loc_xaccm[0] = ~0; /* force escape on 0x00 through 0x1f */
xaccm = loc_xaccm;
}
fcs = PPP_INITFCS; /* Initial FCS is 0xffff */
/*
* Process this block and the rest (if any) attached to the this one
*/
for (tmp = mp; tmp; tmp = tmp->b_cont) {
if (tmp->b_datap->db_type == M_DATA) {
for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
fcs = PPP_FCS(fcs, *dp);
if (IN_TX_MAP(*dp, xaccm)) {
*outmp->b_wptr++ = PPP_ESCAPE;
*outmp->b_wptr++ = *dp ^ PPP_TRANS;
} else {
*outmp->b_wptr++ = *dp;
}
}
} else {
continue; /* skip if db_type is something other than M_DATA */
}
}
/*
* Append the HDLC FCS, making sure that escaping is done on any
* necessary bytes
*/
fcs_val = (fcs ^ 0xffff) & 0xff;
if (IN_TX_MAP(fcs_val, xaccm)) {
*outmp->b_wptr++ = PPP_ESCAPE;
*outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
} else {
*outmp->b_wptr++ = fcs_val;
}
fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
if (IN_TX_MAP(fcs_val, xaccm)) {
*outmp->b_wptr++ = PPP_ESCAPE;
*outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
} else {
*outmp->b_wptr++ = fcs_val;
}
/*
* And finally, append the HDLC flag, and send it away
*/
*outmp->b_wptr++ = PPP_FLAG;
state->stats.ppp_obytes += msgdsize(outmp);
state->stats.ppp_opackets++;
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
putnext(q, outmp);
return;
}
/*
* Checks the 32-bit receive ACCM to see if the byte needs un-escaping
*/
#define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
(m) & (1 << (c)))
/*
* Process received characters.
*/
static void
ahdlc_decode(q, mp)
queue_t *q;
mblk_t *mp;
{
ahdlc_state_t *state;
mblk_t *om;
uchar_t *dp;
state = (ahdlc_state_t *) q->q_ptr;
#if defined(USE_MUTEX)
mutex_enter(&state->lock);
#endif /* USE_MUTEX */
state->stats.ppp_ibytes += msgdsize(mp);
for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
/*
* This should detect the lack of 8-bit communication channel
* which is necessary for PPP to work. In addition, it also
* checks on the parity.
*/
if (*dp & 0x80)
state->flags |= RCV_B7_1;
else
state->flags |= RCV_B7_0;
if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
state->flags |= RCV_ODDP;
else
state->flags |= RCV_EVNP;
/*
* So we have a HDLC flag ...
*/
if (*dp == PPP_FLAG) {
/*
* If we think that it marks the beginning of the frame,
* then continue to process the next octects
*/
if ((state->flags & IFLUSH) ||
(state->rx_buf == 0) ||
(msgdsize(state->rx_buf) == 0)) {
state->flags &= ~IFLUSH;
continue;
}
/*
* We get here because the above condition isn't true,
* in which case the HDLC flag was there to mark the end
* of the frame (or so we think)
*/
om = state->rx_buf;
if (state->infcs == PPP_GOODFCS) {
state->stats.ppp_ipackets++;
adjmsg(om, -PPP_FCSLEN);
putnext(q, om);
} else {
DPRINT2("ppp%d: bad fcs (len=%d)\n",
state->unit, msgdsize(state->rx_buf));
freemsg(state->rx_buf);
state->flags &= ~(IFLUSH | ESCAPED);
state->stats.ppp_ierrors++;
putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
}
state->rx_buf = 0;
continue;
}
if (state->flags & IFLUSH) {
continue;
}
/*
* Allocate a receive buffer, large enough to store a frame (after
* un-escaping) of at least 1500 octets. If MRU is negotiated to
* be more than the default, then allocate that much. In addition,
* we add an extra 32-bytes for a fudge factor
*/
if (state->rx_buf == 0) {
state->rx_buf_size = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
state->rx_buf_size += (sizeof(u_int32_t) << 3);
state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
/*
* If allocation fails, try again on the next frame
*/
if (state->rx_buf == 0) {
state->flags |= IFLUSH;
continue;
}
state->flags &= ~(IFLUSH | ESCAPED);
state->infcs = PPP_INITFCS;
}
if (*dp == PPP_ESCAPE) {
state->flags |= ESCAPED;
continue;
}
/*
* Make sure we un-escape the necessary characters, as well as the
* ones in our receive async control character map
*/
if (state->flags & ESCAPED) {
*dp ^= PPP_TRANS;
state->flags &= ~ESCAPED;
} else if (IN_RX_MAP(*dp, state->raccm))
continue;
/*
* Unless the peer lied to us about the negotiated MRU, we should
* never get a frame which is too long. If it happens, toss it away
* and grab the next incoming one
*/
if (msgdsize(state->rx_buf) < state->rx_buf_size) {
state->infcs = PPP_FCS(state->infcs, *dp);
*state->rx_buf->b_wptr++ = *dp;
} else {
DPRINT2("ppp%d: frame too long (%d)\n",
state->unit, msgdsize(state->rx_buf));
freemsg(state->rx_buf);
state->rx_buf = 0;
state->flags |= IFLUSH;
}
}
#if defined(USE_MUTEX)
mutex_exit(&state->lock);
#endif /* USE_MUTEX */
}
static int
msg_byte(mp, i)
mblk_t *mp;
unsigned int i;
{
while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
mp = mp->b_cont;
if (mp == 0)
return -1;
return mp->b_rptr[i];
}

1134
modules/ppp_comp.c Normal file

File diff suppressed because it is too large Load Diff

190
modules/ppp_mod.h Normal file
View File

@ -0,0 +1,190 @@
/*
* Miscellaneous definitions for PPP STREAMS modules.
*/
/*
* Macros for allocating and freeing kernel memory.
*/
#ifdef SVR4 /* SVR4, including Solaris 2 */
#include <sys/kmem.h>
#define ALLOC_SLEEP(n) kmem_alloc((n), KM_SLEEP)
#define ALLOC_NOSLEEP(n) kmem_alloc((n), KM_NOSLEEP)
#define FREE(p, n) kmem_free((p), (n))
#endif
#ifdef SUNOS4
#include <sys/kmem_alloc.h> /* SunOS 4.x */
#define ALLOC_SLEEP(n) kmem_alloc((n), KMEM_SLEEP)
#define ALLOC_NOSLEEP(n) kmem_alloc((n), KMEM_NOSLEEP)
#define FREE(p, n) kmem_free((p), (n))
#define NOTSUSER() (suser()? 0: EPERM)
#define bcanputnext(q, band) canputnext((q))
#endif /* SunOS 4 */
#ifdef __osf__
#include <sys/malloc.h>
/* caution: this mirrors macros in sys/malloc.h, and uses interfaces
* which are subject to change.
* The problems are that:
* - the official MALLOC macro wants the lhs of the assignment as an argument,
* and it takes care of the assignment itself (yuck.)
* - PPP insists on using "FREE" which conflicts with a macro of the same name.
*
*/
#ifdef BUCKETINDX /* V2.0 */
#define ALLOC_SLEEP(n) (void *)malloc((u_long)(n), BUCKETP(n), M_DEVBUF, M_WAITOK)
#define ALLOC_NOSLEEP(n) (void *)malloc((u_long)(n), BUCKETP(n), M_DEVBUF, M_NOWAIT)
#else
#define ALLOC_SLEEP(n) (void *)malloc((u_long)(n), BUCKETINDEX(n), M_DEVBUF, M_WAITOK)
#define ALLOC_NOSLEEP(n) (void *)malloc((u_long)(n), BUCKETINDEX(n), M_DEVBUF, M_NOWAIT)
#endif
#define bcanputnext(q, band) canputnext((q))
#ifdef FREE
#undef FREE
#endif
#define FREE(p, n) free((void *)(p), M_DEVBUF)
#define NO_DLPI 1
#ifndef IFT_PPP
#define IFT_PPP 0x17
#endif
#include <sys/proc.h>
#define NOTSUSER() (suser(u.u_procp->p_rcred, &u.u_acflag) ? EPERM : 0)
/* #include "ppp_osf.h" */
#endif /* __osf__ */
#ifdef AIX4
#define ALLOC_SLEEP(n) xmalloc((n), 0, pinned_heap) /* AIX V4.x */
#define ALLOC_NOSLEEP(n) xmalloc((n), 0, pinned_heap) /* AIX V4.x */
#define FREE(p, n) xmfree((p), pinned_heap)
#define NOTSUSER() (suser()? 0: EPERM)
#endif /* AIX */
/*
* Macros for printing debugging stuff.
*/
#ifdef DEBUG
#if defined(SVR4) || defined(__osf__)
#if defined(SNI)
#include <sys/strlog.h>
#define STRLOG_ID 4712
#define DPRINT(f) strlog(STRLOG_ID, 0, 0, SL_TRACE, f)
#define DPRINT1(f, a1) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1)
#define DPRINT2(f, a1, a2) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1, a2)
#define DPRINT3(f, a1, a2, a3) strlog(STRLOG_ID, 0, 0, SL_TRACE, f, a1, a2, a3)
#else
#define DPRINT(f) cmn_err(CE_CONT, f)
#define DPRINT1(f, a1) cmn_err(CE_CONT, f, a1)
#define DPRINT2(f, a1, a2) cmn_err(CE_CONT, f, a1, a2)
#define DPRINT3(f, a1, a2, a3) cmn_err(CE_CONT, f, a1, a2, a3)
#endif /* SNI */
#else
#define DPRINT(f) printf(f)
#define DPRINT1(f, a1) printf(f, a1)
#define DPRINT2(f, a1, a2) printf(f, a1, a2)
#define DPRINT3(f, a1, a2, a3) printf(f, a1, a2, a3)
#endif /* SVR4 or OSF */
#else
#define DPRINT(f) 0
#define DPRINT1(f, a1) 0
#define DPRINT2(f, a1, a2) 0
#define DPRINT3(f, a1, a2, a3) 0
#endif /* DEBUG */
#ifndef SVR4
typedef unsigned char uchar_t;
typedef unsigned short ushort_t;
#ifndef __osf__
typedef int minor_t;
#endif
#endif
/*
* If we don't have multithreading support, define substitutes.
*/
#ifndef D_MP
# define qprocson(q)
# define qprocsoff(q)
# define put(q, mp) ((*(q)->q_qinfo->qi_putp)((q), (mp)))
# define canputnext(q) canput((q)->q_next)
# define qwriter(q, mp, func, scope) (func)((q), (mp))
#endif
#ifdef D_MP
/* Use msgpullup if we have other multithreading support. */
#define PULLUP(mp, len) \
do { \
mblk_t *np = msgpullup((mp), (len)); \
freemsg((mp)); \
mp = np; \
} while (0)
#else
/* Use pullupmsg if we don't have any multithreading support. */
#define PULLUP(mp, len) \
do { \
if (!pullupmsg((mp), (len))) { \
freemsg((mp)); \
mp = 0; \
} \
} while (0)
#endif
/*
* How to declare the open and close procedures for a module.
*/
#ifdef SVR4
#define MOD_OPEN_DECL(name) \
static int name __P((queue_t *, dev_t *, int, int, cred_t *))
#define MOD_CLOSE_DECL(name) \
static int name __P((queue_t *, int, cred_t *))
#define MOD_OPEN(name) \
static int name(q, devp, flag, sflag, credp) \
queue_t *q; \
dev_t *devp; \
int flag, sflag; \
cred_t *credp;
#define MOD_CLOSE(name) \
static int name(q, flag, credp) \
queue_t *q; \
int flag; \
cred_t *credp;
#define OPEN_ERROR(x) return (x)
#define DRV_OPEN_OK(dev) return 0
#define NOTSUSER() (drv_priv(credp))
#else /* not SVR4 */
#define MOD_OPEN_DECL(name) \
static int name __P((queue_t *, int, int, int))
#define MOD_CLOSE_DECL(name) \
static int name __P((queue_t *, int))
#define MOD_OPEN(name) \
static int name(q, dev, flag, sflag) \
queue_t *q; \
int dev; \
int flag, sflag;
#define MOD_CLOSE(name) \
static int name(q, flag) \
queue_t *q; \
int flag;
#define OPEN_ERROR(x) { u.u_error = (x); return OPENFAIL; }
#define DRV_OPEN_OK(dev) return (dev)
#endif /* SVR4 */

591
modules/vjcompress.c Normal file
View File

@ -0,0 +1,591 @@
/*
* Routines to compress and uncompess tcp packets (for transmission
* over low speed serial lines.
*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*
* Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au,
* so that the entire packet being decompressed doesn't have
* to be in contiguous memory (just the compressed header).
*/
/*
* This version is used under SunOS 4.x, Digital UNIX, AIX 4.x,
* and SVR4 systems including Solaris 2.
*
* $Id: vjcompress.c,v 1.11 2004/01/17 05:47:55 carlsonj Exp $
*/
#include <sys/types.h>
#include <sys/param.h>
#ifdef SVR4
#ifndef __GNUC__
#include <sys/byteorder.h> /* for ntohl, etc. */
#else
/* make sure we don't get the gnu "fixed" one! */
#include "/usr/include/sys/byteorder.h"
#endif
#endif
#ifdef __osf__
#include <net/net_globals.h>
#endif
#include <netinet/in.h>
#ifdef AIX4
#define _NETINET_IN_SYSTM_H_
typedef u_long n_long;
#else
#include <netinet/in_systm.h>
#endif
#ifdef SOL2
#include <sys/sunddi.h>
#endif
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <net/ppp_defs.h>
#include <net/vjcompress.h>
#ifndef VJ_NO_STATS
#define INCR(counter) ++comp->stats.counter
#else
#define INCR(counter)
#endif
#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))
#undef BCOPY
#define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n))
#ifndef KERNEL
#define ovbcopy bcopy
#endif
#ifdef __osf__
#define getip_hl(base) (((base).ip_vhl)&0xf)
#define getth_off(base) ((((base).th_xoff)&0xf0)>>4)
#else
#define getip_hl(base) ((base).ip_hl)
#define getth_off(base) ((base).th_off)
#endif
void
vj_compress_init(comp, max_state)
struct vjcompress *comp;
int max_state;
{
register u_int i;
register struct cstate *tstate = comp->tstate;
if (max_state == -1)
max_state = MAX_STATES - 1;
bzero((char *)comp, sizeof(*comp));
for (i = max_state; i > 0; --i) {
tstate[i].cs_id = i;
tstate[i].cs_next = &tstate[i - 1];
}
tstate[0].cs_next = &tstate[max_state];
tstate[0].cs_id = 0;
comp->last_cs = &tstate[0];
comp->last_recv = 255;
comp->last_xmit = 255;
comp->flags = VJF_TOSS;
}
/* ENCODE encodes a number that is known to be non-zero. ENCODEZ
* checks for zero (since zero has to be encoded in the long, 3 byte
* form).
*/
#define ENCODE(n) { \
if ((u_short)(n) >= 256) { \
*cp++ = 0; \
cp[1] = (n); \
cp[0] = (n) >> 8; \
cp += 2; \
} else { \
*cp++ = (n); \
} \
}
#define ENCODEZ(n) { \
if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
*cp++ = 0; \
cp[1] = (n); \
cp[0] = (n) >> 8; \
cp += 2; \
} else { \
*cp++ = (n); \
} \
}
#define DECODEL(f) { \
if (*cp == 0) {\
u_int32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \
(f) = htonl(tmp); \
cp += 3; \
} else { \
u_int32_t tmp = ntohl(f) + (u_int32_t)*cp++; \
(f) = htonl(tmp); \
} \
}
#define DECODES(f) { \
if (*cp == 0) {\
u_short tmp = ntohs(f) + ((cp[1] << 8) | cp[2]); \
(f) = htons(tmp); \
cp += 3; \
} else { \
u_short tmp = ntohs(f) + (u_int32_t)*cp++; \
(f) = htons(tmp); \
} \
}
#define DECODEU(f) { \
if (*cp == 0) {\
(f) = htons((cp[1] << 8) | cp[2]); \
cp += 3; \
} else { \
(f) = htons((u_int32_t)*cp++); \
} \
}
u_int
vj_compress_tcp(ip, mlen, comp, compress_cid, vjhdrp)
register struct ip *ip;
u_int mlen;
struct vjcompress *comp;
int compress_cid;
u_char **vjhdrp;
{
register struct cstate *cs = comp->last_cs->cs_next;
register u_int hlen = getip_hl(*ip);
register struct tcphdr *oth;
register struct tcphdr *th;
register u_int deltaS, deltaA;
register u_int changes = 0;
u_char new_seq[16];
register u_char *cp = new_seq;
/*
* Bail if this is an IP fragment or if the TCP packet isn't
* `compressible' (i.e., ACK isn't set or some other control bit is
* set). (We assume that the caller has already made sure the
* packet is IP proto TCP).
*/
if ((ip->ip_off & htons(0x3fff)) || mlen < 40)
return (TYPE_IP);
th = (struct tcphdr *)&((int *)ip)[hlen];
if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
return (TYPE_IP);
/*
* Packet is compressible -- we're going to send either a
* COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
* to locate (or create) the connection state. Special case the
* most recently used connection since it's most likely to be used
* again & we don't have to do any reordering if it's used.
*/
INCR(vjs_packets);
if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
*(int *)th != ((int *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {
/*
* Wasn't the first -- search for it.
*
* States are kept in a circularly linked list with
* last_cs pointing to the end of the list. The
* list is kept in lru order by moving a state to the
* head of the list whenever it is referenced. Since
* the list is short and, empirically, the connection
* we want is almost always near the front, we locate
* states via linear search. If we don't find a state
* for the datagram, the oldest state is (re-)used.
*/
register struct cstate *lcs;
register struct cstate *lastcs = comp->last_cs;
do {
lcs = cs; cs = cs->cs_next;
INCR(vjs_searches);
if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
&& ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
&& *(int *)th == ((int *)&cs->cs_ip)[getip_hl(cs->cs_ip)])
goto found;
} while (cs != lastcs);
/*
* Didn't find it -- re-use oldest cstate. Send an
* uncompressed packet that tells the other side what
* connection number we're using for this conversation.
* Note that since the state list is circular, the oldest
* state points to the newest and we only need to set
* last_cs to update the lru linkage.
*/
INCR(vjs_misses);
comp->last_cs = lcs;
hlen += getth_off(*th);
hlen <<= 2;
if (hlen > mlen)
return (TYPE_IP);
goto uncompressed;
found:
/*
* Found it -- move to the front on the connection list.
*/
if (cs == lastcs)
comp->last_cs = lcs;
else {
lcs->cs_next = cs->cs_next;
cs->cs_next = lastcs->cs_next;
lastcs->cs_next = cs;
}
}
/*
* Make sure that only what we expect to change changed. The first
* line of the `if' checks the IP protocol version, header length &
* type of service. The 2nd line checks the "Don't fragment" bit.
* The 3rd line checks the time-to-live and protocol (the protocol
* check is unnecessary but costless). The 4th line checks the TCP
* header length. The 5th line checks IP options, if any. The 6th
* line checks TCP options, if any. If any of these things are
* different between the previous & current datagram, we send the
* current datagram `uncompressed'.
*/
oth = (struct tcphdr *)&((int *)&cs->cs_ip)[hlen];
deltaS = hlen;
hlen += getth_off(*th);
hlen <<= 2;
if (hlen > mlen)
return (TYPE_IP);
if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] ||
((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] ||
((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] ||
getth_off(*th) != getth_off(*oth) ||
(deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
(getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2)))
goto uncompressed;
/*
* Figure out which of the changing fields changed. The
* receiver expects changes in the order: urgent, window,
* ack, seq (the order minimizes the number of temporaries
* needed in this section of code).
*/
if (th->th_flags & TH_URG) {
deltaS = ntohs(th->th_urp);
ENCODEZ(deltaS);
changes |= NEW_U;
} else if (th->th_urp != oth->th_urp)
/* argh! URG not set but urp changed -- a sensible
* implementation should never do this but RFC793
* doesn't prohibit the change so we have to deal
* with it. */
goto uncompressed;
if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) > 0) {
ENCODE(deltaS);
changes |= NEW_W;
}
if ((deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack)) > 0) {
if (deltaA > 0xffff)
goto uncompressed;
ENCODE(deltaA);
changes |= NEW_A;
}
if ((deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq)) > 0) {
if (deltaS > 0xffff)
goto uncompressed;
ENCODE(deltaS);
changes |= NEW_S;
}
switch(changes) {
case 0:
/*
* Nothing changed. If this packet contains data and the
* last one didn't, this is probably a data packet following
* an ack (normal on an interactive connection) and we send
* it compressed. Otherwise it's probably a retransmit,
* retransmitted ack or window probe. Send it uncompressed
* in case the other side missed the compressed version.
*/
if (ip->ip_len != cs->cs_ip.ip_len &&
ntohs(cs->cs_ip.ip_len) == hlen)
break;
/* (fall through) */
case SPECIAL_I:
case SPECIAL_D:
/*
* actual changes match one of our special case encodings --
* send packet uncompressed.
*/
goto uncompressed;
case NEW_S|NEW_A:
if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
/* special case for echoed terminal traffic */
changes = SPECIAL_I;
cp = new_seq;
}
break;
case NEW_S:
if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
/* special case for data xfer */
changes = SPECIAL_D;
cp = new_seq;
}
break;
}
deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
if (deltaS != 1) {
ENCODEZ(deltaS);
changes |= NEW_I;
}
if (th->th_flags & TH_PUSH)
changes |= TCP_PUSH_BIT;
/*
* Grab the cksum before we overwrite it below. Then update our
* state with this packet's header.
*/
deltaA = ntohs(th->th_sum);
BCOPY(ip, &cs->cs_ip, hlen);
/*
* We want to use the original packet as our compressed packet.
* (cp - new_seq) is the number of bytes we need for compressed
* sequence numbers. In addition we need one byte for the change
* mask, one for the connection id and two for the tcp checksum.
* So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
* many bytes of the original packet to toss so subtract the two to
* get the new packet size.
*/
deltaS = cp - new_seq;
cp = (u_char *)ip;
if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
comp->last_xmit = cs->cs_id;
hlen -= deltaS + 4;
*vjhdrp = (cp += hlen);
*cp++ = changes | NEW_C;
*cp++ = cs->cs_id;
} else {
hlen -= deltaS + 3;
*vjhdrp = (cp += hlen);
*cp++ = changes;
}
*cp++ = deltaA >> 8;
*cp++ = deltaA;
BCOPY(new_seq, cp, deltaS);
INCR(vjs_compressed);
return (TYPE_COMPRESSED_TCP);
/*
* Update connection state cs & send uncompressed packet (that is,
* a regular ip/tcp packet but with the 'conversation id' we hope
* to use on future compressed packets in the protocol field).
*/
uncompressed:
BCOPY(ip, &cs->cs_ip, hlen);
ip->ip_p = cs->cs_id;
comp->last_xmit = cs->cs_id;
return (TYPE_UNCOMPRESSED_TCP);
}
/*
* Called when we may have missed a packet.
*/
void
vj_uncompress_err(comp)
struct vjcompress *comp;
{
comp->flags |= VJF_TOSS;
INCR(vjs_errorin);
}
/*
* "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
*/
int
vj_uncompress_uncomp(buf, buflen, comp)
u_char *buf;
int buflen;
struct vjcompress *comp;
{
register u_int hlen;
register struct cstate *cs;
register struct ip *ip;
ip = (struct ip *) buf;
hlen = getip_hl(*ip) << 2;
if (ip->ip_p >= MAX_STATES
|| hlen + sizeof(struct tcphdr) > buflen
|| (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2)
> buflen
|| hlen > MAX_HDR) {
comp->flags |= VJF_TOSS;
INCR(vjs_errorin);
return (0);
}
cs = &comp->rstate[comp->last_recv = ip->ip_p];
comp->flags &=~ VJF_TOSS;
ip->ip_p = IPPROTO_TCP;
BCOPY(ip, &cs->cs_ip, hlen);
cs->cs_hlen = hlen;
INCR(vjs_uncompressedin);
return (1);
}
/*
* Uncompress a packet of type TYPE_COMPRESSED_TCP.
* The packet starts at buf and is of total length total_len.
* The first buflen bytes are at buf; this must include the entire
* compressed TCP/IP header. This procedure returns the length
* of the VJ header, with a pointer to the uncompressed IP header
* in *hdrp and its length in *hlenp.
*/
int
vj_uncompress_tcp(buf, buflen, total_len, comp, hdrp, hlenp)
u_char *buf;
int buflen, total_len;
struct vjcompress *comp;
u_char **hdrp;
u_int *hlenp;
{
register u_char *cp;
register u_int hlen, changes;
register struct tcphdr *th;
register struct cstate *cs;
register u_short *bp;
register u_int vjlen;
register u_int32_t tmp;
INCR(vjs_compressedin);
cp = buf;
changes = *cp++;
if (changes & NEW_C) {
/* Make sure the state index is in range, then grab the state.
* If we have a good state index, clear the 'discard' flag. */
if (*cp >= MAX_STATES)
goto bad;
comp->flags &=~ VJF_TOSS;
comp->last_recv = *cp++;
} else {
/* this packet has an implicit state index. If we've
* had a line error since the last time we got an
* explicit state index, we have to toss the packet. */
if (comp->flags & VJF_TOSS) {
INCR(vjs_tossed);
return (-1);
}
}
cs = &comp->rstate[comp->last_recv];
hlen = getip_hl(cs->cs_ip) << 2;
th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
th->th_sum = htons((*cp << 8) | cp[1]);
cp += 2;
if (changes & TCP_PUSH_BIT)
th->th_flags |= TH_PUSH;
else
th->th_flags &=~ TH_PUSH;
switch (changes & SPECIALS_MASK) {
case SPECIAL_I:
{
register u_int32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
/* some compilers can't nest inline assembler.. */
tmp = ntohl(th->th_ack) + i;
th->th_ack = htonl(tmp);
tmp = ntohl(th->th_seq) + i;
th->th_seq = htonl(tmp);
}
break;
case SPECIAL_D:
/* some compilers can't nest inline assembler.. */
tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
th->th_seq = htonl(tmp);
break;
default:
if (changes & NEW_U) {
th->th_flags |= TH_URG;
DECODEU(th->th_urp);
} else
th->th_flags &=~ TH_URG;
if (changes & NEW_W)
DECODES(th->th_win);
if (changes & NEW_A)
DECODEL(th->th_ack);
if (changes & NEW_S)
DECODEL(th->th_seq);
break;
}
if (changes & NEW_I) {
DECODES(cs->cs_ip.ip_id);
} else {
cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1;
cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id);
}
/*
* At this point, cp points to the first byte of data in the
* packet. Fill in the IP total length and update the IP
* header checksum.
*/
vjlen = cp - buf;
buflen -= vjlen;
if (buflen < 0)
/* we must have dropped some characters (crc should detect
* this but the old slip framing won't) */
goto bad;
total_len += cs->cs_hlen - vjlen;
cs->cs_ip.ip_len = htons(total_len);
/* recompute the ip header checksum */
bp = (u_short *) &cs->cs_ip;
cs->cs_ip.ip_sum = 0;
for (changes = 0; hlen > 0; hlen -= 2)
changes += *bp++;
changes = (changes & 0xffff) + (changes >> 16);
changes = (changes & 0xffff) + (changes >> 16);
cs->cs_ip.ip_sum = ~ changes;
*hdrp = (u_char *) &cs->cs_ip;
*hlenp = cs->cs_hlen;
return vjlen;
bad:
comp->flags |= VJF_TOSS;
INCR(vjs_errorin);
return (-1);
}

1
pppd/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
pppd

230
pppd/Makefile.linux Normal file
View File

@ -0,0 +1,230 @@
#
# pppd makefile for Linux
# $Id: Makefile.linux,v 1.70 2007/06/19 02:08:34 carlsonj Exp $
#
# Default installation locations
DESTDIR = $(INSTROOT)@DESTDIR@
BINDIR = $(DESTDIR)/sbin
MANDIR = $(DESTDIR)/share/man/man8
INCDIR = $(DESTDIR)/include
TARGETS = pppd
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap-new.c md5.c ccp.c \
ecp.c ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c \
demand.c utils.c tty.c eap.c chap-md5.c session.c
HEADERS = ccp.h session.h chap-new.h ecp.h fsm.h ipcp.h \
ipxcp.h lcp.h magic.h md5.h patchlevel.h pathnames.h pppd.h \
upap.h eap.h
MANPAGES = pppd.8
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap-new.o md5.o ccp.o \
ecp.o auth.o options.o demand.o utils.o sys-linux.o ipxcp.o tty.o \
eap.o chap-md5.o session.o
#
# include dependencies if present
ifeq (.depend,$(wildcard .depend))
include .depend
endif
# CC = gcc
#
COPTS = -O2 -pipe -Wall -g
LIBS =
# Uncomment the next 2 lines to include support for Microsoft's
# MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux.
CHAPMS=y
USE_CRYPT=y
# Don't use MSLANMAN unless you really know what you're doing.
#MSLANMAN=y
# Uncomment the next line to include support for MPPE. CHAPMS (above) must
# also be enabled. Also, edit plugins/radius/Makefile.linux.
MPPE=y
# Uncomment the next line to include support for PPP packet filtering.
# This requires that the libpcap library and headers be installed
# and that the kernel driver support PPP packet filtering.
FILTER=y
# Uncomment the next line to enable multilink PPP (enabled by default)
# Linux distributions: Please leave multilink ENABLED in your builds
# of pppd!
HAVE_MULTILINK=y
# Uncomment the next line to enable the TDB database (enabled by default.)
# If you enable multilink, then TDB is automatically enabled also.
# Linux distributions: Please leave TDB ENABLED in your builds.
USE_TDB=y
HAS_SHADOW=y
#USE_PAM=y
HAVE_INET6=y
# Enable plugins
PLUGIN=y
# Enable Microsoft proprietary Callback Control Protocol
#CBCP=y
# Enable EAP SRP-SHA1 authentication (requires libsrp)
#USE_SRP=y
# Use libutil
USE_LIBUTIL=y
MAXOCTETS=y
INCLUDE_DIRS= -I../include
COMPILE_FLAGS= -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MMAP
CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS) '-DDESTDIR="@DESTDIR@"'
ifdef CHAPMS
CFLAGS += -DCHAPMS=1
NEEDDES=y
PPPDOBJS += md4.o chap_ms.o
HEADERS += md4.h chap_ms.h
ifdef MSLANMAN
CFLAGS += -DMSLANMAN=1
endif
ifdef MPPE
CFLAGS += -DMPPE=1
endif
endif
# EAP SRP-SHA1
ifdef USE_SRP
CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include
LIBS += -lsrp -L/usr/local/ssl/lib -lcrypto
TARGETS += srp-entry
EXTRAINSTALL = $(INSTALL) -s -c -m 555 srp-entry $(BINDIR)/srp-entry
MANPAGES += srp-entry.8
EXTRACLEAN += srp-entry.o
NEEDDES=y
else
# OpenSSL has an integrated version of SHA-1, and its implementation
# is incompatible with this local SHA-1 implementation. We must use
# one or the other, not both.
PPPDSRCS += sha1.c
HEADERS += sha1.h
PPPDOBJS += sha1.o
endif
ifdef HAS_SHADOW
CFLAGS += -DHAS_SHADOW
#LIBS += -lshadow $(LIBS)
endif
ifneq ($(wildcard /usr/include/crypt.h),)
CFLAGS += -DHAVE_CRYPT_H=1
LIBS += -lcrypt
endif
ifdef USE_LIBUTIL
CFLAGS += -DHAVE_LOGWTMP=1
LIBS += -lutil
endif
ifdef NEEDDES
ifndef USE_CRYPT
LIBS += -ldes $(LIBS)
else
CFLAGS += -DUSE_CRYPT=1
endif
PPPDOBJS += pppcrypt.o
HEADERS += pppcrypt.h
endif
# For "Pluggable Authentication Modules", see ftp.redhat.com:/pub/pam/.
ifdef USE_PAM
CFLAGS += -DUSE_PAM
LIBS += -lpam -ldl
endif
# Multi-linnk
ifdef HAVE_MULTILINK
# Multilink implies the use of TDB
USE_TDB=y
CFLAGS += -DHAVE_MULTILINK
PPPDSRCS += multilink.c
PPPDOBJS += multilink.o
endif
# TDB
ifdef USE_TDB
CFLAGS += -DUSE_TDB=1
PPPDSRCS += tdb.c spinlock.c
PPPDOBJS += tdb.o spinlock.o
HEADERS += tdb.h spinlock.h
endif
# Lock library binary for Linux is included in 'linux' subdirectory.
ifdef LOCKLIB
LIBS += -llock
CFLAGS += -DLOCKLIB=1
endif
ifdef PLUGIN
CFLAGS += -DPLUGIN
LDFLAGS += -Wl,-E
LIBS += -ldl
endif
ifdef FILTER
ifneq ($(wildcard /usr/include/pcap-bpf.h),)
LIBS += -lpcap
CFLAGS += -DPPP_FILTER
endif
endif
ifdef HAVE_INET6
PPPDSRCS += ipv6cp.c eui64.c
HEADERS += ipv6cp.h eui64.h
PPPDOBJS += ipv6cp.o eui64.o
CFLAGS += -DINET6=1
endif
ifdef CBCP
PPPDSRCS += cbcp.c
PPPDOBJS += cbcp.o
CFLAGS += -DCBCP_SUPPORT
HEADERS += cbcp.h
endif
ifdef MAXOCTETS
CFLAGS += -DMAXOCTETS
endif
INSTALL= install
all: $(TARGETS)
install: pppd
mkdir -p $(BINDIR) $(MANDIR)
$(EXTRAINSTALL)
$(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd
if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \
chmod o-rx,u+s $(BINDIR)/pppd; fi
$(INSTALL) -c -m 444 pppd.8 $(MANDIR)
pppd: $(PPPDOBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o pppd $(PPPDOBJS) $(LIBS)
srp-entry: srp-entry.c
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ srp-entry.c $(LIBS)
install-devel:
mkdir -p $(INCDIR)/pppd
$(INSTALL) -c -m 644 $(HEADERS) $(INCDIR)/pppd
clean:
rm -f $(PPPDOBJS) $(EXTRACLEAN) $(TARGETS) *~ #* core
depend:
$(CPP) -M $(CFLAGS) $(PPPDSRCS) >.depend

63
pppd/Makefile.sol2 Normal file
View File

@ -0,0 +1,63 @@
#
# Makefile for pppd under Solaris 2.
# $Id: Makefile.sol2,v 1.30 2008/01/30 14:26:52 carlsonj Exp $
#
include ../Makedefs.com
CFLAGS = -I../include -DSVR4 -DSOL2 $(COPTS) '-DDESTDIR="@DESTDIR@"'
LIBS = -lsocket -lnsl
OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap-new.o eap.o md5.o \
tty.o ccp.o ecp.o auth.o options.o demand.o utils.o sys-solaris.o \
chap-md5.o session.o
# Solaris uses shadow passwords
CFLAGS += -DHAS_SHADOW
#
# Comment the following out to disable plugins
#
CFLAGS += -DPLUGIN
LIBS += -ldl
#
# Solaris 8 and above accomodates /var/run, so uncomment the
# following to place pppd process IDs on that location
#
#CFLAGS += -D_PATH_VARRUN='"/var/run/"'
#
# uncomment the following to enable IPv6
#
# Solaris 8 and on includes support for IPv6
#
CFLAGS += -DINET6
OBJS += ipv6cp.o eui64.o
# Uncomment to enable MS-CHAP
CFLAGS += -DUSE_CRYPT -DCHAPMS -DMSLANMAN -DHAVE_CRYPT_H
OBJS += chap_ms.o pppcrypt.o md4.o sha1.o
# Uncomment for CBCP
#CFLAGS += -DCBCP_SUPPORT
#OBJS += cbcp.o
# Uncomment for PAM
#CFLAGS += -DUSE_PAM
#LIBS += -lpam
#
# Make targets
#
all: pppd
pppd: $(OBJS)
$(CC) -o pppd $(OBJS) $(LIBS)
install:
$(INSTALL) -f $(BINDIR) -m 4755 -u root pppd
$(INSTALL) -f $(MANDIR)/man8 -m 444 pppd.8
clean:
rm -f $(OBJS) pppd *~ core y.tab.c y.tab.h

2361
pppd/auth.c Normal file

File diff suppressed because it is too large Load Diff

488
pppd/cbcp.c Normal file
View File

@ -0,0 +1,488 @@
/*
* cbcp - Call Back Configuration Protocol.
*
* Copyright (c) 1995 Pedro Roque Marques. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Pedro Roque Marques
* <pedro_m@yahoo.com>"
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: cbcp.c,v 1.17 2006/05/22 00:04:07 paulus Exp $"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include "pppd.h"
#include "cbcp.h"
#include "fsm.h"
#include "lcp.h"
static const char rcsid[] = RCSID;
/*
* Options.
*/
static int setcbcp __P((char **));
static option_t cbcp_option_list[] = {
{ "callback", o_special, (void *)setcbcp,
"Ask for callback", OPT_PRIO | OPT_A2STRVAL, &cbcp[0].us_number },
{ NULL }
};
/*
* Protocol entry points.
*/
static void cbcp_init __P((int unit));
static void cbcp_open __P((int unit));
static void cbcp_lowerup __P((int unit));
static void cbcp_input __P((int unit, u_char *pkt, int len));
static void cbcp_protrej __P((int unit));
static int cbcp_printpkt __P((u_char *pkt, int len,
void (*printer) __P((void *, char *, ...)),
void *arg));
struct protent cbcp_protent = {
PPP_CBCP,
cbcp_init,
cbcp_input,
cbcp_protrej,
cbcp_lowerup,
NULL,
cbcp_open,
NULL,
cbcp_printpkt,
NULL,
0,
"CBCP",
NULL,
cbcp_option_list,
NULL,
NULL,
NULL
};
cbcp_state cbcp[NUM_PPP];
/* internal prototypes */
static void cbcp_recvreq __P((cbcp_state *us, u_char *pckt, int len));
static void cbcp_resp __P((cbcp_state *us));
static void cbcp_up __P((cbcp_state *us));
static void cbcp_recvack __P((cbcp_state *us, u_char *pckt, int len));
static void cbcp_send __P((cbcp_state *us, int code, u_char *buf, int len));
/* option processing */
static int
setcbcp(argv)
char **argv;
{
lcp_wantoptions[0].neg_cbcp = 1;
cbcp_protent.enabled_flag = 1;
cbcp[0].us_number = strdup(*argv);
if (cbcp[0].us_number == 0)
novm("callback number");
cbcp[0].us_type |= (1 << CB_CONF_USER);
cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
return (1);
}
/* init state */
static void
cbcp_init(iface)
int iface;
{
cbcp_state *us;
us = &cbcp[iface];
memset(us, 0, sizeof(cbcp_state));
us->us_unit = iface;
us->us_type |= (1 << CB_CONF_NO);
}
/* lower layer is up */
static void
cbcp_lowerup(iface)
int iface;
{
cbcp_state *us = &cbcp[iface];
dbglog("cbcp_lowerup");
dbglog("want: %d", us->us_type);
if (us->us_type == CB_CONF_USER)
dbglog("phone no: %s", us->us_number);
}
static void
cbcp_open(unit)
int unit;
{
dbglog("cbcp_open");
}
/* process an incomming packet */
static void
cbcp_input(unit, inpacket, pktlen)
int unit;
u_char *inpacket;
int pktlen;
{
u_char *inp;
u_char code, id;
u_short len;
cbcp_state *us = &cbcp[unit];
inp = inpacket;
if (pktlen < CBCP_MINLEN) {
if (debug)
dbglog("CBCP packet is too small");
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len > pktlen || len < CBCP_MINLEN) {
if (debug)
dbglog("CBCP packet: invalid length %d", len);
return;
}
len -= CBCP_MINLEN;
switch(code) {
case CBCP_REQ:
us->us_id = id;
cbcp_recvreq(us, inp, len);
break;
case CBCP_RESP:
if (debug)
dbglog("CBCP_RESP received");
break;
case CBCP_ACK:
if (debug && id != us->us_id)
dbglog("id doesn't match: expected %d recv %d",
us->us_id, id);
cbcp_recvack(us, inp, len);
break;
default:
break;
}
}
/* protocol was rejected by foe */
void cbcp_protrej(int iface)
{
}
char *cbcp_codenames[] = {
"Request", "Response", "Ack"
};
char *cbcp_optionnames[] = {
"NoCallback",
"UserDefined",
"AdminDefined",
"List"
};
/* pretty print a packet */
static int
cbcp_printpkt(p, plen, printer, arg)
u_char *p;
int plen;
void (*printer) __P((void *, char *, ...));
void *arg;
{
int code, opt, id, len, olen, delay;
u_char *pstart;
if (plen < HEADERLEN)
return 0;
pstart = p;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < HEADERLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
printer(arg, " %s", cbcp_codenames[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= HEADERLEN;
switch (code) {
case CBCP_REQ:
case CBCP_RESP:
case CBCP_ACK:
while(len >= 2) {
GETCHAR(opt, p);
GETCHAR(olen, p);
if (olen < 2 || olen > len) {
break;
}
printer(arg, " <");
len -= olen;
if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
printer(arg, " %s", cbcp_optionnames[opt-1]);
else
printer(arg, " option=0x%x", opt);
if (olen > 2) {
GETCHAR(delay, p);
printer(arg, " delay = %d", delay);
}
if (olen > 3) {
int addrt;
char str[256];
GETCHAR(addrt, p);
memcpy(str, p, olen - 4);
str[olen - 4] = 0;
printer(arg, " number = %s", str);
}
printer(arg, ">");
}
break;
default:
break;
}
for (; len > 0; --len) {
GETCHAR(code, p);
printer(arg, " %.2x", code);
}
return p - pstart;
}
/* received CBCP request */
static void
cbcp_recvreq(us, pckt, pcktlen)
cbcp_state *us;
u_char *pckt;
int pcktlen;
{
u_char type, opt_len, delay, addr_type;
char address[256];
int len = pcktlen;
address[0] = 0;
while (len >= 2) {
dbglog("length: %d", len);
GETCHAR(type, pckt);
GETCHAR(opt_len, pckt);
if (opt_len < 2 || opt_len > len)
break;
if (opt_len > 2)
GETCHAR(delay, pckt);
us->us_allowed |= (1 << type);
switch(type) {
case CB_CONF_NO:
dbglog("no callback allowed");
break;
case CB_CONF_USER:
dbglog("user callback allowed");
if (opt_len > 4) {
GETCHAR(addr_type, pckt);
memcpy(address, pckt, opt_len - 4);
address[opt_len - 4] = 0;
if (address[0])
dbglog("address: %s", address);
}
break;
case CB_CONF_ADMIN:
dbglog("user admin defined allowed");
break;
case CB_CONF_LIST:
break;
}
len -= opt_len;
}
if (len != 0) {
if (debug)
dbglog("cbcp_recvreq: malformed packet (%d bytes left)", len);
return;
}
cbcp_resp(us);
}
static void
cbcp_resp(us)
cbcp_state *us;
{
u_char cb_type;
u_char buf[256];
u_char *bufp = buf;
int len = 0;
int slen;
cb_type = us->us_allowed & us->us_type;
dbglog("cbcp_resp cb_type=%d", cb_type);
#if 0
if (!cb_type)
lcp_down(us->us_unit);
#endif
if (cb_type & ( 1 << CB_CONF_USER ) ) {
dbglog("cbcp_resp CONF_USER");
slen = strlen(us->us_number);
if (slen > 250) {
warn("callback number truncated to 250 characters");
slen = 250;
}
PUTCHAR(CB_CONF_USER, bufp);
len = 3 + 1 + slen + 1;
PUTCHAR(len , bufp);
PUTCHAR(5, bufp); /* delay */
PUTCHAR(1, bufp);
BCOPY(us->us_number, bufp, slen + 1);
cbcp_send(us, CBCP_RESP, buf, len);
return;
}
if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
dbglog("cbcp_resp CONF_ADMIN");
PUTCHAR(CB_CONF_ADMIN, bufp);
len = 3;
PUTCHAR(len, bufp);
PUTCHAR(5, bufp); /* delay */
cbcp_send(us, CBCP_RESP, buf, len);
return;
}
if (cb_type & ( 1 << CB_CONF_NO ) ) {
dbglog("cbcp_resp CONF_NO");
PUTCHAR(CB_CONF_NO, bufp);
len = 2;
PUTCHAR(len , bufp);
cbcp_send(us, CBCP_RESP, buf, len);
start_networks(us->us_unit);
return;
}
}
static void
cbcp_send(us, code, buf, len)
cbcp_state *us;
int code;
u_char *buf;
int len;
{
u_char *outp;
int outlen;
outp = outpacket_buf;
outlen = 4 + len;
MAKEHEADER(outp, PPP_CBCP);
PUTCHAR(code, outp);
PUTCHAR(us->us_id, outp);
PUTSHORT(outlen, outp);
if (len)
BCOPY(buf, outp, len);
output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
}
static void
cbcp_recvack(us, pckt, len)
cbcp_state *us;
u_char *pckt;
int len;
{
u_char type, delay, addr_type;
int opt_len;
char address[256];
if (len >= 2) {
GETCHAR(type, pckt);
GETCHAR(opt_len, pckt);
if (opt_len >= 2 && opt_len <= len) {
if (opt_len > 2)
GETCHAR(delay, pckt);
if (opt_len > 4) {
GETCHAR(addr_type, pckt);
memcpy(address, pckt, opt_len - 4);
address[opt_len - 4] = 0;
if (address[0])
dbglog("peer will call: %s", address);
}
if (type == CB_CONF_NO)
return;
cbcp_up(us);
} else if (debug)
dbglog("cbcp_recvack: malformed packet");
}
}
/* ok peer will do callback */
static void
cbcp_up(us)
cbcp_state *us;
{
persist = 0;
status = EXIT_CALLBACK;
lcp_close(0, "Call me back, please");
}

26
pppd/cbcp.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef CBCP_H
#define CBCP_H
typedef struct cbcp_state {
int us_unit; /* Interface unit number */
u_char us_id; /* Current id */
u_char us_allowed;
int us_type;
char *us_number; /* Telefone Number */
} cbcp_state;
extern cbcp_state cbcp[];
extern struct protent cbcp_protent;
#define CBCP_MINLEN 4
#define CBCP_REQ 1
#define CBCP_RESP 2
#define CBCP_ACK 3
#define CB_CONF_NO 1
#define CB_CONF_USER 2
#define CB_CONF_ADMIN 3
#define CB_CONF_LIST 4
#endif

1678
pppd/ccp.c Normal file

File diff suppressed because it is too large Load Diff

52
pppd/ccp.h Normal file
View File

@ -0,0 +1,52 @@
/*
* ccp.h - Definitions for PPP Compression Control Protocol.
*
* Copyright (c) 1994-2002 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $
*/
typedef struct ccp_options {
bool bsd_compress; /* do BSD Compress? */
bool deflate; /* do Deflate? */
bool predictor_1; /* do Predictor-1? */
bool predictor_2; /* do Predictor-2? */
bool deflate_correct; /* use correct code for deflate? */
bool deflate_draft; /* use draft RFC code for deflate? */
bool mppe; /* do MPPE? */
u_short bsd_bits; /* # bits/code for BSD Compress */
u_short deflate_size; /* lg(window size) for Deflate */
short method; /* code for chosen compression method */
} ccp_options;
extern fsm ccp_fsm[];
extern ccp_options ccp_wantoptions[];
extern ccp_options ccp_gotoptions[];
extern ccp_options ccp_allowoptions[];
extern ccp_options ccp_hisoptions[];
extern struct protent ccp_protent;

117
pppd/chap-md5.c Normal file
View File

@ -0,0 +1,117 @@
/*
* chap-md5.c - New CHAP/MD5 implementation.
*
* Copyright (c) 2003 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: chap-md5.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
#include <stdlib.h>
#include <string.h>
#include "pppd.h"
#include "chap-new.h"
#include "chap-md5.h"
#include "magic.h"
#include "md5.h"
#define MD5_HASH_SIZE 16
#define MD5_MIN_CHALLENGE 16
#define MD5_MAX_CHALLENGE 24
static void
chap_md5_generate_challenge(unsigned char *cp)
{
int clen;
clen = (int)(drand48() * (MD5_MAX_CHALLENGE - MD5_MIN_CHALLENGE))
+ MD5_MIN_CHALLENGE;
*cp++ = clen;
random_bytes(cp, clen);
}
static int
chap_md5_verify_response(int id, char *name,
unsigned char *secret, int secret_len,
unsigned char *challenge, unsigned char *response,
char *message, int message_space)
{
MD5_CTX ctx;
unsigned char idbyte = id;
unsigned char hash[MD5_HASH_SIZE];
int challenge_len, response_len;
challenge_len = *challenge++;
response_len = *response++;
if (response_len == MD5_HASH_SIZE) {
/* Generate hash of ID, secret, challenge */
MD5_Init(&ctx);
MD5_Update(&ctx, &idbyte, 1);
MD5_Update(&ctx, secret, secret_len);
MD5_Update(&ctx, challenge, challenge_len);
MD5_Final(hash, &ctx);
/* Test if our hash matches the peer's response */
if (memcmp(hash, response, MD5_HASH_SIZE) == 0) {
slprintf(message, message_space, "Access granted");
return 1;
}
}
slprintf(message, message_space, "Access denied");
return 0;
}
static void
chap_md5_make_response(unsigned char *response, int id, char *our_name,
unsigned char *challenge, char *secret, int secret_len,
unsigned char *private)
{
MD5_CTX ctx;
unsigned char idbyte = id;
int challenge_len = *challenge++;
MD5_Init(&ctx);
MD5_Update(&ctx, &idbyte, 1);
MD5_Update(&ctx, (u_char *)secret, secret_len);
MD5_Update(&ctx, challenge, challenge_len);
MD5_Final(&response[1], &ctx);
response[0] = MD5_HASH_SIZE;
}
static struct chap_digest_type md5_digest = {
CHAP_MD5, /* code */
chap_md5_generate_challenge,
chap_md5_verify_response,
chap_md5_make_response,
NULL, /* check_success */
NULL, /* handle_failure */
};
void
chap_md5_init(void)
{
chap_register_digest(&md5_digest);
}

31
pppd/chap-md5.h Normal file
View File

@ -0,0 +1,31 @@
/*
* chap-md5.h - New CHAP/MD5 implementation.
*
* Copyright (c) 2003 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
extern void chap_md5_init(void);

656
pppd/chap-new.c Normal file
View File

@ -0,0 +1,656 @@
/*
* chap-new.c - New CHAP implementation.
*
* Copyright (c) 2003 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: chap-new.c,v 1.9 2007/06/19 02:08:35 carlsonj Exp $"
#include <stdlib.h>
#include <string.h>
#include "pppd.h"
#include "session.h"
#include "chap-new.h"
#include "chap-md5.h"
#ifdef CHAPMS
#include "chap_ms.h"
#define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5)
#else
#define MDTYPE_ALL (MDTYPE_MD5)
#endif
int chap_mdtype_all = MDTYPE_ALL;
/* Hook for a plugin to validate CHAP challenge */
int (*chap_verify_hook)(char *name, char *ourname, int id,
struct chap_digest_type *digest,
unsigned char *challenge, unsigned char *response,
char *message, int message_space) = NULL;
/*
* Option variables.
*/
int chap_timeout_time = 3;
int chap_max_transmits = 10;
int chap_rechallenge_time = 0;
/*
* Command-line options.
*/
static option_t chap_option_list[] = {
{ "chap-restart", o_int, &chap_timeout_time,
"Set timeout for CHAP", OPT_PRIO },
{ "chap-max-challenge", o_int, &chap_max_transmits,
"Set max #xmits for challenge", OPT_PRIO },
{ "chap-interval", o_int, &chap_rechallenge_time,
"Set interval for rechallenge", OPT_PRIO },
{ NULL }
};
/*
* Internal state.
*/
static struct chap_client_state {
int flags;
char *name;
struct chap_digest_type *digest;
unsigned char priv[64]; /* private area for digest's use */
} client;
/*
* These limits apply to challenge and response packets we send.
* The +4 is the +1 that we actually need rounded up.
*/
#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN)
#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN)
static struct chap_server_state {
int flags;
int id;
char *name;
struct chap_digest_type *digest;
int challenge_xmits;
int challenge_pktlen;
unsigned char challenge[CHAL_MAX_PKTLEN];
char message[256];
} server;
/* Values for flags in chap_client_state and chap_server_state */
#define LOWERUP 1
#define AUTH_STARTED 2
#define AUTH_DONE 4
#define AUTH_FAILED 8
#define TIMEOUT_PENDING 0x10
#define CHALLENGE_VALID 0x20
/*
* Prototypes.
*/
static void chap_init(int unit);
static void chap_lowerup(int unit);
static void chap_lowerdown(int unit);
static void chap_timeout(void *arg);
static void chap_generate_challenge(struct chap_server_state *ss);
static void chap_handle_response(struct chap_server_state *ss, int code,
unsigned char *pkt, int len);
static int chap_verify_response(char *name, char *ourname, int id,
struct chap_digest_type *digest,
unsigned char *challenge, unsigned char *response,
char *message, int message_space);
static void chap_respond(struct chap_client_state *cs, int id,
unsigned char *pkt, int len);
static void chap_handle_status(struct chap_client_state *cs, int code, int id,
unsigned char *pkt, int len);
static void chap_protrej(int unit);
static void chap_input(int unit, unsigned char *pkt, int pktlen);
static int chap_print_pkt(unsigned char *p, int plen,
void (*printer) __P((void *, char *, ...)), void *arg);
/* List of digest types that we know about */
static struct chap_digest_type *chap_digests;
/*
* chap_init - reset to initial state.
*/
static void
chap_init(int unit)
{
memset(&client, 0, sizeof(client));
memset(&server, 0, sizeof(server));
chap_md5_init();
#ifdef CHAPMS
chapms_init();
#endif
}
/*
* Add a new digest type to the list.
*/
void
chap_register_digest(struct chap_digest_type *dp)
{
dp->next = chap_digests;
chap_digests = dp;
}
/*
* chap_lowerup - we can start doing stuff now.
*/
static void
chap_lowerup(int unit)
{
struct chap_client_state *cs = &client;
struct chap_server_state *ss = &server;
cs->flags |= LOWERUP;
ss->flags |= LOWERUP;
if (ss->flags & AUTH_STARTED)
chap_timeout(ss);
}
static void
chap_lowerdown(int unit)
{
struct chap_client_state *cs = &client;
struct chap_server_state *ss = &server;
cs->flags = 0;
if (ss->flags & TIMEOUT_PENDING)
UNTIMEOUT(chap_timeout, ss);
ss->flags = 0;
}
/*
* chap_auth_peer - Start authenticating the peer.
* If the lower layer is already up, we start sending challenges,
* otherwise we wait for the lower layer to come up.
*/
void
chap_auth_peer(int unit, char *our_name, int digest_code)
{
struct chap_server_state *ss = &server;
struct chap_digest_type *dp;
if (ss->flags & AUTH_STARTED) {
error("CHAP: peer authentication already started!");
return;
}
for (dp = chap_digests; dp != NULL; dp = dp->next)
if (dp->code == digest_code)
break;
if (dp == NULL)
fatal("CHAP digest 0x%x requested but not available",
digest_code);
ss->digest = dp;
ss->name = our_name;
/* Start with a random ID value */
ss->id = (unsigned char)(drand48() * 256);
ss->flags |= AUTH_STARTED;
if (ss->flags & LOWERUP)
chap_timeout(ss);
}
/*
* chap_auth_with_peer - Prepare to authenticate ourselves to the peer.
* There isn't much to do until we receive a challenge.
*/
void
chap_auth_with_peer(int unit, char *our_name, int digest_code)
{
struct chap_client_state *cs = &client;
struct chap_digest_type *dp;
if (cs->flags & AUTH_STARTED) {
error("CHAP: authentication with peer already started!");
return;
}
for (dp = chap_digests; dp != NULL; dp = dp->next)
if (dp->code == digest_code)
break;
if (dp == NULL)
fatal("CHAP digest 0x%x requested but not available",
digest_code);
cs->digest = dp;
cs->name = our_name;
cs->flags |= AUTH_STARTED;
}
/*
* chap_timeout - It's time to send another challenge to the peer.
* This could be either a retransmission of a previous challenge,
* or a new challenge to start re-authentication.
*/
static void
chap_timeout(void *arg)
{
struct chap_server_state *ss = arg;
ss->flags &= ~TIMEOUT_PENDING;
if ((ss->flags & CHALLENGE_VALID) == 0) {
ss->challenge_xmits = 0;
chap_generate_challenge(ss);
ss->flags |= CHALLENGE_VALID;
} else if (ss->challenge_xmits >= chap_max_transmits) {
ss->flags &= ~CHALLENGE_VALID;
ss->flags |= AUTH_DONE | AUTH_FAILED;
auth_peer_fail(0, PPP_CHAP);
return;
}
output(0, ss->challenge, ss->challenge_pktlen);
++ss->challenge_xmits;
ss->flags |= TIMEOUT_PENDING;
TIMEOUT(chap_timeout, arg, chap_timeout_time);
}
/*
* chap_generate_challenge - generate a challenge string and format
* the challenge packet in ss->challenge_pkt.
*/
static void
chap_generate_challenge(struct chap_server_state *ss)
{
int clen = 1, nlen, len;
unsigned char *p;
p = ss->challenge;
MAKEHEADER(p, PPP_CHAP);
p += CHAP_HDRLEN;
ss->digest->generate_challenge(p);
clen = *p;
nlen = strlen(ss->name);
memcpy(p + 1 + clen, ss->name, nlen);
len = CHAP_HDRLEN + 1 + clen + nlen;
ss->challenge_pktlen = PPP_HDRLEN + len;
p = ss->challenge + PPP_HDRLEN;
p[0] = CHAP_CHALLENGE;
p[1] = ++ss->id;
p[2] = len >> 8;
p[3] = len;
}
/*
* chap_handle_response - check the response to our challenge.
*/
static void
chap_handle_response(struct chap_server_state *ss, int id,
unsigned char *pkt, int len)
{
int response_len, ok, mlen;
unsigned char *response, *p;
char *name = NULL; /* initialized to shut gcc up */
int (*verifier)(char *, char *, int, struct chap_digest_type *,
unsigned char *, unsigned char *, char *, int);
char rname[MAXNAMELEN+1];
if ((ss->flags & LOWERUP) == 0)
return;
if (id != ss->challenge[PPP_HDRLEN+1] || len < 2)
return;
if (ss->flags & CHALLENGE_VALID) {
response = pkt;
GETCHAR(response_len, pkt);
len -= response_len + 1; /* length of name */
name = (char *)pkt + response_len;
if (len < 0)
return;
if (ss->flags & TIMEOUT_PENDING) {
ss->flags &= ~TIMEOUT_PENDING;
UNTIMEOUT(chap_timeout, ss);
}
if (explicit_remote) {
name = remote_name;
} else {
/* Null terminate and clean remote name. */
slprintf(rname, sizeof(rname), "%.*v", len, name);
name = rname;
}
if (chap_verify_hook)
verifier = chap_verify_hook;
else
verifier = chap_verify_response;
ok = (*verifier)(name, ss->name, id, ss->digest,
ss->challenge + PPP_HDRLEN + CHAP_HDRLEN,
response, ss->message, sizeof(ss->message));
if (!ok || !auth_number()) {
ss->flags |= AUTH_FAILED;
warn("Peer %q failed CHAP authentication", name);
}
} else if ((ss->flags & AUTH_DONE) == 0)
return;
/* send the response */
p = outpacket_buf;
MAKEHEADER(p, PPP_CHAP);
mlen = strlen(ss->message);
len = CHAP_HDRLEN + mlen;
p[0] = (ss->flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS;
p[1] = id;
p[2] = len >> 8;
p[3] = len;
if (mlen > 0)
memcpy(p + CHAP_HDRLEN, ss->message, mlen);
output(0, outpacket_buf, PPP_HDRLEN + len);
if (ss->flags & CHALLENGE_VALID) {
ss->flags &= ~CHALLENGE_VALID;
if (!(ss->flags & AUTH_DONE) && !(ss->flags & AUTH_FAILED)) {
/*
* Auth is OK, so now we need to check session restrictions
* to ensure everything is OK, but only if we used a
* plugin, and only if we're configured to check. This
* allows us to do PAM checks on PPP servers that
* authenticate against ActiveDirectory, and use AD for
* account info (like when using Winbind integrated with
* PAM).
*/
if (session_mgmt &&
session_check(name, NULL, devnam, NULL) == 0) {
ss->flags |= AUTH_FAILED;
warn("Peer %q failed CHAP Session verification", name);
}
}
if (ss->flags & AUTH_FAILED) {
auth_peer_fail(0, PPP_CHAP);
} else {
if ((ss->flags & AUTH_DONE) == 0)
auth_peer_success(0, PPP_CHAP,
ss->digest->code,
name, strlen(name));
if (chap_rechallenge_time) {
ss->flags |= TIMEOUT_PENDING;
TIMEOUT(chap_timeout, ss,
chap_rechallenge_time);
}
}
ss->flags |= AUTH_DONE;
}
}
/*
* chap_verify_response - check whether the peer's response matches
* what we think it should be. Returns 1 if it does (authentication
* succeeded), or 0 if it doesn't.
*/
static int
chap_verify_response(char *name, char *ourname, int id,
struct chap_digest_type *digest,
unsigned char *challenge, unsigned char *response,
char *message, int message_space)
{
int ok;
unsigned char secret[MAXSECRETLEN];
int secret_len;
/* Get the secret that the peer is supposed to know */
if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
error("No CHAP secret found for authenticating %q", name);
return 0;
}
ok = digest->verify_response(id, name, secret, secret_len, challenge,
response, message, message_space);
memset(secret, 0, sizeof(secret));
return ok;
}
/*
* chap_respond - Generate and send a response to a challenge.
*/
static void
chap_respond(struct chap_client_state *cs, int id,
unsigned char *pkt, int len)
{
int clen, nlen;
int secret_len;
unsigned char *p;
unsigned char response[RESP_MAX_PKTLEN];
char rname[MAXNAMELEN+1];
char secret[MAXSECRETLEN+1];
if ((cs->flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED))
return; /* not ready */
if (len < 2 || len < pkt[0] + 1)
return; /* too short */
clen = pkt[0];
nlen = len - (clen + 1);
/* Null terminate and clean remote name. */
slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1);
/* Microsoft doesn't send their name back in the PPP packet */
if (explicit_remote || (remote_name[0] != 0 && rname[0] == 0))
strlcpy(rname, remote_name, sizeof(rname));
/* get secret for authenticating ourselves with the specified host */
if (!get_secret(0, cs->name, rname, secret, &secret_len, 0)) {
secret_len = 0; /* assume null secret if can't find one */
warn("No CHAP secret found for authenticating us to %q", rname);
}
p = response;
MAKEHEADER(p, PPP_CHAP);
p += CHAP_HDRLEN;
cs->digest->make_response(p, id, cs->name, pkt,
secret, secret_len, cs->priv);
memset(secret, 0, secret_len);
clen = *p;
nlen = strlen(cs->name);
memcpy(p + clen + 1, cs->name, nlen);
p = response + PPP_HDRLEN;
len = CHAP_HDRLEN + clen + 1 + nlen;
p[0] = CHAP_RESPONSE;
p[1] = id;
p[2] = len >> 8;
p[3] = len;
output(0, response, PPP_HDRLEN + len);
}
static void
chap_handle_status(struct chap_client_state *cs, int code, int id,
unsigned char *pkt, int len)
{
const char *msg = NULL;
if ((cs->flags & (AUTH_DONE|AUTH_STARTED|LOWERUP))
!= (AUTH_STARTED|LOWERUP))
return;
cs->flags |= AUTH_DONE;
if (code == CHAP_SUCCESS) {
/* used for MS-CHAP v2 mutual auth, yuck */
if (cs->digest->check_success != NULL) {
if (!(*cs->digest->check_success)(id, pkt, len))
code = CHAP_FAILURE;
} else
msg = "CHAP authentication succeeded";
} else {
if (cs->digest->handle_failure != NULL)
(*cs->digest->handle_failure)(pkt, len);
else
msg = "CHAP authentication failed";
}
if (msg) {
if (len > 0)
info("%s: %.*v", msg, len, pkt);
else
info("%s", msg);
}
if (code == CHAP_SUCCESS)
auth_withpeer_success(0, PPP_CHAP, cs->digest->code);
else {
cs->flags |= AUTH_FAILED;
error("CHAP authentication failed");
auth_withpeer_fail(0, PPP_CHAP);
}
}
static void
chap_input(int unit, unsigned char *pkt, int pktlen)
{
struct chap_client_state *cs = &client;
struct chap_server_state *ss = &server;
unsigned char code, id;
int len;
if (pktlen < CHAP_HDRLEN)
return;
GETCHAR(code, pkt);
GETCHAR(id, pkt);
GETSHORT(len, pkt);
if (len < CHAP_HDRLEN || len > pktlen)
return;
len -= CHAP_HDRLEN;
switch (code) {
case CHAP_CHALLENGE:
chap_respond(cs, id, pkt, len);
break;
case CHAP_RESPONSE:
chap_handle_response(ss, id, pkt, len);
break;
case CHAP_FAILURE:
case CHAP_SUCCESS:
chap_handle_status(cs, code, id, pkt, len);
break;
}
}
static void
chap_protrej(int unit)
{
struct chap_client_state *cs = &client;
struct chap_server_state *ss = &server;
if (ss->flags & TIMEOUT_PENDING) {
ss->flags &= ~TIMEOUT_PENDING;
UNTIMEOUT(chap_timeout, ss);
}
if (ss->flags & AUTH_STARTED) {
ss->flags = 0;
auth_peer_fail(0, PPP_CHAP);
}
if ((cs->flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) {
cs->flags &= ~AUTH_STARTED;
error("CHAP authentication failed due to protocol-reject");
auth_withpeer_fail(0, PPP_CHAP);
}
}
/*
* chap_print_pkt - print the contents of a CHAP packet.
*/
static char *chap_code_names[] = {
"Challenge", "Response", "Success", "Failure"
};
static int
chap_print_pkt(unsigned char *p, int plen,
void (*printer) __P((void *, char *, ...)), void *arg)
{
int code, id, len;
int clen, nlen;
unsigned char x;
if (plen < CHAP_HDRLEN)
return 0;
GETCHAR(code, p);
GETCHAR(id, p);
GETSHORT(len, p);
if (len < CHAP_HDRLEN || len > plen)
return 0;
if (code >= 1 && code <= sizeof(chap_code_names) / sizeof(char *))
printer(arg, " %s", chap_code_names[code-1]);
else
printer(arg, " code=0x%x", code);
printer(arg, " id=0x%x", id);
len -= CHAP_HDRLEN;
switch (code) {
case CHAP_CHALLENGE:
case CHAP_RESPONSE:
if (len < 1)
break;
clen = p[0];
if (len < clen + 1)
break;
++p;
nlen = len - clen - 1;
printer(arg, " <");
for (; clen > 0; --clen) {
GETCHAR(x, p);
printer(arg, "%.2x", x);
}
printer(arg, ">, name = ");
print_string((char *)p, nlen, printer, arg);
break;
case CHAP_FAILURE:
case CHAP_SUCCESS:
printer(arg, " ");
print_string((char *)p, len, printer, arg);
break;
default:
for (clen = len; clen > 0; --clen) {
GETCHAR(x, p);
printer(arg, " %.2x", x);
}
}
return len + CHAP_HDRLEN;
}
struct protent chap_protent = {
PPP_CHAP,
chap_init,
chap_input,
chap_protrej,
chap_lowerup,
chap_lowerdown,
NULL, /* open */
NULL, /* close */
chap_print_pkt,
NULL, /* datainput */
1, /* enabled_flag */
"CHAP", /* name */
NULL, /* data_name */
chap_option_list,
NULL, /* check_options */
};

130
pppd/chap-new.h Normal file
View File

@ -0,0 +1,130 @@
/*
* chap-new.c - New CHAP implementation.
*
* Copyright (c) 2003 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* CHAP packets begin with a standard header with code, id, len (2 bytes).
*/
#define CHAP_HDRLEN 4
/*
* Values for the code field.
*/
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
#define CHAP_FAILURE 4
/*
* CHAP digest codes.
*/
#define CHAP_MD5 5
#define CHAP_MICROSOFT 0x80
#define CHAP_MICROSOFT_V2 0x81
/*
* Semi-arbitrary limits on challenge and response fields.
*/
#define MAX_CHALLENGE_LEN 64
#define MAX_RESPONSE_LEN 64
/* bitmask of supported algorithms */
#define MDTYPE_MICROSOFT_V2 0x1
#define MDTYPE_MICROSOFT 0x2
#define MDTYPE_MD5 0x4
#define MDTYPE_NONE 0
/* hashes supported by this instance of pppd */
extern int chap_mdtype_all;
/* Return the digest alg. ID for the most preferred digest type. */
#define CHAP_DIGEST(mdtype) \
((mdtype) & MDTYPE_MD5)? CHAP_MD5: \
((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \
((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \
0
/* Return the bit flag (lsb set) for our most preferred digest type. */
#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype)
/* Return the bit flag for a given digest algorithm ID. */
#define CHAP_MDTYPE_D(digest) \
((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \
((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \
((digest) == CHAP_MD5)? MDTYPE_MD5: \
0
/* Can we do the requested digest? */
#define CHAP_CANDIGEST(mdtype, digest) \
((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \
((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \
((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \
0
/*
* The code for each digest type has to supply one of these.
*/
struct chap_digest_type {
int code;
/*
* Note: challenge and response arguments below are formatted as
* a length byte followed by the actual challenge/response data.
*/
void (*generate_challenge)(unsigned char *challenge);
int (*verify_response)(int id, char *name,
unsigned char *secret, int secret_len,
unsigned char *challenge, unsigned char *response,
char *message, int message_space);
void (*make_response)(unsigned char *response, int id, char *our_name,
unsigned char *challenge, char *secret, int secret_len,
unsigned char *priv);
int (*check_success)(int id, unsigned char *pkt, int len);
void (*handle_failure)(unsigned char *pkt, int len);
struct chap_digest_type *next;
};
/* Hook for a plugin to validate CHAP challenge */
extern int (*chap_verify_hook)(char *name, char *ourname, int id,
struct chap_digest_type *digest,
unsigned char *challenge, unsigned char *response,
char *message, int message_space);
/* Called by digest code to register a digest type */
extern void chap_register_digest(struct chap_digest_type *);
/* Called by authentication code to start authenticating the peer. */
extern void chap_auth_peer(int unit, char *our_name, int digest_code);
/* Called by auth. code to start authenticating us to the peer. */
extern void chap_auth_with_peer(int unit, char *our_name, int digest_code);
/* Represents the CHAP protocol to the main pppd code */
extern struct protent chap_protent;

1006
pppd/chap_ms.c Normal file

File diff suppressed because it is too large Load Diff

109
pppd/chap_ms.h Normal file
View File

@ -0,0 +1,109 @@
/*
* chap_ms.h - Challenge Handshake Authentication Protocol definitions.
*
* Copyright (c) 1995 Eric Rosenquist. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $
*/
#ifndef __CHAPMS_INCLUDE__
#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */
#define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */
#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */
#define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */
#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */
/* as ASCII */
/* E=eeeeeeeeee error codes for MS-CHAP failure messages. */
#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS 646
#define MS_CHAP_ERROR_ACCT_DISABLED 647
#define MS_CHAP_ERROR_PASSWD_EXPIRED 648
#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION 649
#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE 691
#define MS_CHAP_ERROR_CHANGING_PASSWORD 709
/*
* Offsets within the response field for MS-CHAP
*/
#define MS_CHAP_LANMANRESP 0
#define MS_CHAP_LANMANRESP_LEN 24
#define MS_CHAP_NTRESP 24
#define MS_CHAP_NTRESP_LEN 24
#define MS_CHAP_USENT 48
/*
* Offsets within the response field for MS-CHAP2
*/
#define MS_CHAP2_PEER_CHALLENGE 0
#define MS_CHAP2_PEER_CHAL_LEN 16
#define MS_CHAP2_RESERVED_LEN 8
#define MS_CHAP2_NTRESP 24
#define MS_CHAP2_NTRESP_LEN 24
#define MS_CHAP2_FLAGS 48
#ifdef MPPE
#include "mppe.h" /* MPPE_MAX_KEY_LEN */
extern u_char mppe_send_key[MPPE_MAX_KEY_LEN];
extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
extern int mppe_keys_set;
/* These values are the RADIUS attribute values--see RFC 2548. */
#define MPPE_ENC_POL_ENC_ALLOWED 1
#define MPPE_ENC_POL_ENC_REQUIRED 2
#define MPPE_ENC_TYPES_RC4_40 2
#define MPPE_ENC_TYPES_RC4_128 4
/* used by plugins (using above values) */
extern void set_mppe_enc_types(int, int);
#endif
/* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */
#define MS_CHAP2_AUTHENTICATEE 0
#define MS_CHAP2_AUTHENTICATOR 1
void ChapMS __P((u_char *, char *, int, u_char *));
void ChapMS2 __P((u_char *, u_char *, char *, char *, int,
u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int));
#ifdef MPPE
void mppe_set_keys __P((u_char *, u_char[MD4_SIGNATURE_SIZE]));
void mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
u_char NTResponse[24], int IsServer);
#endif
void ChallengeHash __P((u_char[16], u_char *, char *, u_char[8]));
void GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
u_char NTResponse[24], u_char PeerChallenge[16],
u_char *rchallenge, char *username,
u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]);
void chapms_init(void);
#define __CHAPMS_INCLUDE__
#endif /* __CHAPMS_INCLUDE__ */

364
pppd/demand.c Normal file
View File

@ -0,0 +1,364 @@
/*
* demand.c - Support routines for demand-dialling.
*
* Copyright (c) 1996-2002 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: demand.c,v 1.20 2005/08/25 12:14:18 paulus Exp $"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#ifdef PPP_FILTER
#include <pcap-bpf.h>
#endif
#include "pppd.h"
#include "fsm.h"
#include "ipcp.h"
#include "lcp.h"
static const char rcsid[] = RCSID;
char *frame;
int framelen;
int framemax;
int escape_flag;
int flush_flag;
int fcs;
struct packet {
int length;
struct packet *next;
unsigned char data[1];
};
struct packet *pend_q;
struct packet *pend_qtail;
static int active_packet __P((unsigned char *, int));
/*
* demand_conf - configure the interface for doing dial-on-demand.
*/
void
demand_conf()
{
int i;
struct protent *protp;
/* framemax = lcp_allowoptions[0].mru;
if (framemax < PPP_MRU) */
framemax = PPP_MRU;
framemax += PPP_HDRLEN + PPP_FCSLEN;
frame = malloc(framemax);
if (frame == NULL)
novm("demand frame");
framelen = 0;
pend_q = NULL;
escape_flag = 0;
flush_flag = 0;
fcs = PPP_INITFCS;
netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0
|| ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0)
fatal("Couldn't set up demand-dialled PPP interface: %m");
#ifdef PPP_FILTER
set_filters(&pass_filter, &active_filter);
#endif
/*
* Call the demand_conf procedure for each protocol that's got one.
*/
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
if (!((*protp->demand_conf)(0)))
die(1);
}
/*
* demand_block - set each network protocol to block further packets.
*/
void
demand_block()
{
int i;
struct protent *protp;
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
get_loop_output();
}
/*
* demand_discard - set each network protocol to discard packets
* with an error.
*/
void
demand_discard()
{
struct packet *pkt, *nextpkt;
int i;
struct protent *protp;
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
get_loop_output();
/* discard all saved packets */
for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
nextpkt = pkt->next;
free(pkt);
}
pend_q = NULL;
framelen = 0;
flush_flag = 0;
escape_flag = 0;
fcs = PPP_INITFCS;
}
/*
* demand_unblock - set each enabled network protocol to pass packets.
*/
void
demand_unblock()
{
int i;
struct protent *protp;
for (i = 0; (protp = protocols[i]) != NULL; ++i)
if (protp->enabled_flag && protp->demand_conf != NULL)
sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
}
/*
* FCS lookup table as calculated by genfcstab.
*/
static u_short fcstab[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
/*
* loop_chars - process characters received from the loopback.
* Calls loop_frame when a complete frame has been accumulated.
* Return value is 1 if we need to bring up the link, 0 otherwise.
*/
int
loop_chars(p, n)
unsigned char *p;
int n;
{
int c, rv;
rv = 0;
for (; n > 0; --n) {
c = *p++;
if (c == PPP_FLAG) {
if (!escape_flag && !flush_flag
&& framelen > 2 && fcs == PPP_GOODFCS) {
framelen -= 2;
if (loop_frame((unsigned char *)frame, framelen))
rv = 1;
}
framelen = 0;
flush_flag = 0;
escape_flag = 0;
fcs = PPP_INITFCS;
continue;
}
if (flush_flag)
continue;
if (escape_flag) {
c ^= PPP_TRANS;
escape_flag = 0;
} else if (c == PPP_ESCAPE) {
escape_flag = 1;
continue;
}
if (framelen >= framemax) {
flush_flag = 1;
continue;
}
frame[framelen++] = c;
fcs = PPP_FCS(fcs, c);
}
return rv;
}
/*
* loop_frame - given a frame obtained from the loopback,
* decide whether to bring up the link or not, and, if we want
* to transmit this frame later, put it on the pending queue.
* Return value is 1 if we need to bring up the link, 0 otherwise.
* We assume that the kernel driver has already applied the
* pass_filter, so we won't get packets it rejected.
* We apply the active_filter to see if we want this packet to
* bring up the link.
*/
int
loop_frame(frame, len)
unsigned char *frame;
int len;
{
struct packet *pkt;
/* dbglog("from loop: %P", frame, len); */
if (len < PPP_HDRLEN)
return 0;
if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
return 0; /* shouldn't get any of these anyway */
if (!active_packet(frame, len))
return 0;
pkt = (struct packet *) malloc(sizeof(struct packet) + len);
if (pkt != NULL) {
pkt->length = len;
pkt->next = NULL;
memcpy(pkt->data, frame, len);
if (pend_q == NULL)
pend_q = pkt;
else
pend_qtail->next = pkt;
pend_qtail = pkt;
}
return 1;
}
/*
* demand_rexmit - Resend all those frames which we got via the
* loopback, now that the real serial link is up.
*/
void
demand_rexmit(proto)
int proto;
{
struct packet *pkt, *prev, *nextpkt;
prev = NULL;
pkt = pend_q;
pend_q = NULL;
for (; pkt != NULL; pkt = nextpkt) {
nextpkt = pkt->next;
if (PPP_PROTOCOL(pkt->data) == proto) {
output(0, pkt->data, pkt->length);
free(pkt);
} else {
if (prev == NULL)
pend_q = pkt;
else
prev->next = pkt;
prev = pkt;
}
}
pend_qtail = prev;
if (prev != NULL)
prev->next = NULL;
}
/*
* Scan a packet to decide whether it is an "active" packet,
* that is, whether it is worth bringing up the link for.
*/
static int
active_packet(p, len)
unsigned char *p;
int len;
{
int proto, i;
struct protent *protp;
if (len < PPP_HDRLEN)
return 0;
proto = PPP_PROTOCOL(p);
#ifdef PPP_FILTER
p[0] = 1; /* outbound packet indicator */
if ((pass_filter.bf_len != 0
&& bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
|| (active_filter.bf_len != 0
&& bpf_filter(active_filter.bf_insns, p, len, len) == 0)) {
p[0] = 0xff;
return 0;
}
p[0] = 0xff;
#endif
for (i = 0; (protp = protocols[i]) != NULL; ++i) {
if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
if (!protp->enabled_flag)
return 0;
if (protp->active_pkt == NULL)
return 1;
return (*protp->active_pkt)(p, len);
}
}
return 0; /* not a supported protocol !!?? */
}

2428
pppd/eap.c Normal file

File diff suppressed because it is too large Load Diff

158
pppd/eap.h Normal file
View File

@ -0,0 +1,158 @@
/*
* eap.h - Extensible Authentication Protocol for PPP (RFC 2284)
*
* Copyright (c) 2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* Non-exclusive rights to redistribute, modify, translate, and use
* this software in source and binary forms, in whole or in part, is
* hereby granted, provided that the above copyright notice is
* duplicated in any source form, and that neither the name of the
* copyright holder nor the author is used to endorse or promote
* products derived from this software.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Original version by James Carlson
*
* $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $
*/
#ifndef PPP_EAP_H
#define PPP_EAP_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Packet header = Code, id, length.
*/
#define EAP_HEADERLEN 4
/* EAP message codes. */
#define EAP_REQUEST 1
#define EAP_RESPONSE 2
#define EAP_SUCCESS 3
#define EAP_FAILURE 4
/* EAP types */
#define EAPT_IDENTITY 1
#define EAPT_NOTIFICATION 2
#define EAPT_NAK 3 /* (response only) */
#define EAPT_MD5CHAP 4
#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */
#define EAPT_TOKEN 6 /* Generic Token Card */
/* 7 and 8 are unassigned. */
#define EAPT_RSA 9 /* RSA Public Key Authentication */
#define EAPT_DSS 10 /* DSS Unilateral */
#define EAPT_KEA 11 /* KEA */
#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */
#define EAPT_TLS 13 /* EAP-TLS */
#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */
#define EAPT_W2K 15 /* Windows 2000 EAP */
#define EAPT_ARCOT 16 /* Arcot Systems */
#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */
#define EAPT_NOKIACARD 18 /* Nokia IP smart card */
#define EAPT_SRP 19 /* Secure Remote Password */
/* 20 is deprecated */
/* EAP SRP-SHA1 Subtypes */
#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */
#define EAPSRP_CKEY 1 /* Response 1 - Client Key */
#define EAPSRP_SKEY 2 /* Request 2 - Server Key */
#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */
#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */
#define EAPSRP_ACK 3 /* Response 3 - final ack */
#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */
#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */
#define SRP_PSEUDO_ID "pseudo_"
#define SRP_PSEUDO_LEN 7
#define MD5_SIGNATURE_SIZE 16
#define MIN_CHALLENGE_LENGTH 16
#define MAX_CHALLENGE_LENGTH 24
enum eap_state_code {
eapInitial = 0, /* No EAP authentication yet requested */
eapPending, /* Waiting for LCP (no timer) */
eapClosed, /* Authentication not in use */
eapListen, /* Client ready (and timer running) */
eapIdentify, /* EAP Identify sent */
eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */
eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */
eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */
eapMD5Chall, /* Sent MD5-Challenge */
eapOpen, /* Completed authentication */
eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */
eapBadAuth /* Failed authentication */
};
#define EAP_STATES \
"Initial", "Pending", "Closed", "Listen", "Identify", \
"SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth"
#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
#define eap_server_active(esp) \
((esp)->es_server.ea_state >= eapIdentify && \
(esp)->es_server.ea_state <= eapMD5Chall)
struct eap_auth {
char *ea_name; /* Our name */
char *ea_peer; /* Peer's name */
void *ea_session; /* Authentication library linkage */
u_char *ea_skey; /* Shared encryption key */
int ea_timeout; /* Time to wait (for retransmit/fail) */
int ea_maxrequests; /* Max Requests allowed */
u_short ea_namelen; /* Length of our name */
u_short ea_peerlen; /* Length of peer's name */
enum eap_state_code ea_state;
u_char ea_id; /* Current id */
u_char ea_requests; /* Number of Requests sent/received */
u_char ea_responses; /* Number of Responses */
u_char ea_type; /* One of EAPT_* */
u_int32_t ea_keyflags; /* SRP shared key usage flags */
};
/*
* Complete EAP state for one PPP session.
*/
typedef struct eap_state {
int es_unit; /* Interface unit number */
struct eap_auth es_client; /* Client (authenticatee) data */
struct eap_auth es_server; /* Server (authenticator) data */
int es_savedtime; /* Saved timeout */
int es_rechallenge; /* EAP rechallenge interval */
int es_lwrechallenge; /* SRP lightweight rechallenge inter */
bool es_usepseudo; /* Use SRP Pseudonym if offered one */
int es_usedpseudo; /* Set if we already sent PN */
int es_challen; /* Length of challenge string */
u_char es_challenge[MAX_CHALLENGE_LENGTH];
} eap_state;
/*
* Timeouts.
*/
#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */
#define EAP_DEFTRANSMITS 10 /* max # times to transmit */
#define EAP_DEFREQTIME 20 /* Time to wait for peer request */
#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */
extern eap_state eap_states[];
void eap_authwithpeer __P((int unit, char *localname));
void eap_authpeer __P((int unit, char *localname));
extern struct protent eap_protent;
#ifdef __cplusplus
}
#endif
#endif /* PPP_EAP_H */

173
pppd/ecp.c Normal file
View File

@ -0,0 +1,173 @@
/*
* ecp.c - PPP Encryption Control Protocol.
*
* Copyright (c) 2002 Google, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Derived from ccp.c, which is:
*
* Copyright (c) 1994-2002 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: ecp.c,v 1.4 2004/11/04 10:02:26 paulus Exp $"
static const char rcsid[] = RCSID;
#include <string.h>
#include "pppd.h"
#include "fsm.h"
#include "ecp.h"
static option_t ecp_option_list[] = {
{ "noecp", o_bool, &ecp_protent.enabled_flag,
"Disable ECP negotiation" },
{ "-ecp", o_bool, &ecp_protent.enabled_flag,
"Disable ECP negotiation", OPT_ALIAS },
{ NULL }
};
/*
* Protocol entry points from main code.
*/
static void ecp_init __P((int unit));
/*
static void ecp_open __P((int unit));
static void ecp_close __P((int unit, char *));
static void ecp_lowerup __P((int unit));
static void ecp_lowerdown __P((int));
static void ecp_input __P((int unit, u_char *pkt, int len));
static void ecp_protrej __P((int unit));
*/
static int ecp_printpkt __P((u_char *pkt, int len,
void (*printer) __P((void *, char *, ...)),
void *arg));
/*
static void ecp_datainput __P((int unit, u_char *pkt, int len));
*/
struct protent ecp_protent = {
PPP_ECP,
ecp_init,
NULL, /* ecp_input, */
NULL, /* ecp_protrej, */
NULL, /* ecp_lowerup, */
NULL, /* ecp_lowerdown, */
NULL, /* ecp_open, */
NULL, /* ecp_close, */
ecp_printpkt,
NULL, /* ecp_datainput, */
0,
"ECP",
"Encrypted",
ecp_option_list,
NULL,
NULL,
NULL
};
fsm ecp_fsm[NUM_PPP];
ecp_options ecp_wantoptions[NUM_PPP]; /* what to request the peer to use */
ecp_options ecp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
ecp_options ecp_allowoptions[NUM_PPP]; /* what we'll agree to do */
ecp_options ecp_hisoptions[NUM_PPP]; /* what we agreed to do */
static fsm_callbacks ecp_callbacks = {
NULL, /* ecp_resetci, */
NULL, /* ecp_cilen, */
NULL, /* ecp_addci, */
NULL, /* ecp_ackci, */
NULL, /* ecp_nakci, */
NULL, /* ecp_rejci, */
NULL, /* ecp_reqci, */
NULL, /* ecp_up, */
NULL, /* ecp_down, */
NULL,
NULL,
NULL,
NULL,
NULL, /* ecp_extcode, */
"ECP"
};
/*
* ecp_init - initialize ECP.
*/
static void
ecp_init(unit)
int unit;
{
fsm *f = &ecp_fsm[unit];
f->unit = unit;
f->protocol = PPP_ECP;
f->callbacks = &ecp_callbacks;
fsm_init(f);
memset(&ecp_wantoptions[unit], 0, sizeof(ecp_options));
memset(&ecp_gotoptions[unit], 0, sizeof(ecp_options));
memset(&ecp_allowoptions[unit], 0, sizeof(ecp_options));
memset(&ecp_hisoptions[unit], 0, sizeof(ecp_options));
}
static int
ecp_printpkt(p, plen, printer, arg)
u_char *p;
int plen;
void (*printer) __P((void *, char *, ...));
void *arg;
{
return 0;
}

45
pppd/ecp.h Normal file
View File

@ -0,0 +1,45 @@
/*
* ecp.h - Definitions for PPP Encryption Control Protocol.
*
* Copyright (c) 2002 Google, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $
*/
typedef struct ecp_options {
bool required; /* Is ECP required? */
unsigned enctype; /* Encryption type */
} ecp_options;
extern fsm ecp_fsm[];
extern ecp_options ecp_wantoptions[];
extern ecp_options ecp_gotoptions[];
extern ecp_options ecp_allowoptions[];
extern ecp_options ecp_hisoptions[];
extern struct protent ecp_protent;

57
pppd/eui64.c Normal file
View File

@ -0,0 +1,57 @@
/*
* eui64.c - EUI64 routines for IPv6CP.
*
* Copyright (c) 1999 Tommi Komulainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Tommi Komulainen
* <Tommi.Komulainen@iki.fi>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $
*/
#define RCSID "$Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $"
#include "pppd.h"
static const char rcsid[] = RCSID;
/*
* eui64_ntoa - Make an ascii representation of an interface identifier
*/
char *
eui64_ntoa(e)
eui64_t e;
{
static char buf[32];
snprintf(buf, 32, "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
e.e8[0], e.e8[1], e.e8[2], e.e8[3],
e.e8[4], e.e8[5], e.e8[6], e.e8[7]);
return buf;
}

114
pppd/eui64.h Normal file
View File

@ -0,0 +1,114 @@
/*
* eui64.h - EUI64 routines for IPv6CP.
*
* Copyright (c) 1999 Tommi Komulainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Tommi Komulainen
* <Tommi.Komulainen@iki.fi>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: eui64.h,v 1.6 2002/12/04 23:03:32 paulus Exp $
*/
#ifndef __EUI64_H__
#define __EUI64_H__
#if !defined(INET6)
#error "this file should only be included when INET6 is defined"
#endif /* not defined(INET6) */
#if defined(SOL2)
#include <netinet/in.h>
typedef union {
uint8_t e8[8]; /* lower 64-bit IPv6 address */
uint32_t e32[2]; /* lower 64-bit IPv6 address */
} eui64_t;
/*
* Declare the two below, since in.h only defines them when _KERNEL
* is declared - which shouldn't be true when dealing with user-land programs
*/
#define s6_addr8 _S6_un._S6_u8
#define s6_addr32 _S6_un._S6_u32
#else /* else if not defined(SOL2) */
/*
* TODO:
*
* Maybe this should be done by processing struct in6_addr directly...
*/
typedef union
{
u_int8_t e8[8];
u_int16_t e16[4];
u_int32_t e32[2];
} eui64_t;
#endif /* defined(SOL2) */
#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0)
#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \
((e).e32[1] == (o).e32[1]))
#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0;
#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t))
#define eui64_magic(e) do { \
(e).e32[0] = magic(); \
(e).e32[1] = magic(); \
(e).e8[0] &= ~2; \
} while (0)
#define eui64_magic_nz(x) do { \
eui64_magic(x); \
} while (eui64_iszero(x))
#define eui64_magic_ne(x, y) do { \
eui64_magic(x); \
} while (eui64_equals(x, y))
#define eui64_get(ll, cp) do { \
eui64_copy((*cp), (ll)); \
(cp) += sizeof(eui64_t); \
} while (0)
#define eui64_put(ll, cp) do { \
eui64_copy((ll), (*cp)); \
(cp) += sizeof(eui64_t); \
} while (0)
#define eui64_set32(e, l) do { \
(e).e32[0] = 0; \
(e).e32[1] = htonl(l); \
} while (0)
#define eui64_setlo32(e, l) eui64_set32(e, l)
char *eui64_ntoa __P((eui64_t)); /* Returns ascii representation of id */
#endif /* __EUI64_H__ */

817
pppd/fsm.c Normal file
View File

@ -0,0 +1,817 @@
/*
* fsm.c - {Link, IP} Control Protocol Finite State Machine.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: fsm.c,v 1.23 2004/11/13 02:28:15 paulus Exp $"
/*
* TODO:
* Randomize fsm id on link/init.
* Deal with variable outgoing MTU.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "pppd.h"
#include "fsm.h"
static const char rcsid[] = RCSID;
static void fsm_timeout __P((void *));
static void fsm_rconfreq __P((fsm *, int, u_char *, int));
static void fsm_rconfack __P((fsm *, int, u_char *, int));
static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));
static void fsm_rtermreq __P((fsm *, int, u_char *, int));
static void fsm_rtermack __P((fsm *));
static void fsm_rcoderej __P((fsm *, u_char *, int));
static void fsm_sconfreq __P((fsm *, int));
#define PROTO_NAME(f) ((f)->callbacks->proto_name)
int peer_mru[NUM_PPP];
/*
* fsm_init - Initialize fsm.
*
* Initialize fsm state.
*/
void
fsm_init(f)
fsm *f;
{
f->state = INITIAL;
f->flags = 0;
f->id = 0; /* XXX Start with random id? */
f->timeouttime = DEFTIMEOUT;
f->maxconfreqtransmits = DEFMAXCONFREQS;
f->maxtermtransmits = DEFMAXTERMREQS;
f->maxnakloops = DEFMAXNAKLOOPS;
f->term_reason_len = 0;
}
/*
* fsm_lowerup - The lower layer is up.
*/
void
fsm_lowerup(f)
fsm *f;
{
switch( f->state ){
case INITIAL:
f->state = CLOSED;
break;
case STARTING:
if( f->flags & OPT_SILENT )
f->state = STOPPED;
else {
/* Send an initial configure-request */
fsm_sconfreq(f, 0);
f->state = REQSENT;
}
break;
default:
FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state));
}
}
/*
* fsm_lowerdown - The lower layer is down.
*
* Cancel all timeouts and inform upper layers.
*/
void
fsm_lowerdown(f)
fsm *f;
{
switch( f->state ){
case CLOSED:
f->state = INITIAL;
break;
case STOPPED:
f->state = STARTING;
if( f->callbacks->starting )
(*f->callbacks->starting)(f);
break;
case CLOSING:
f->state = INITIAL;
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
break;
case STOPPING:
case REQSENT:
case ACKRCVD:
case ACKSENT:
f->state = STARTING;
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
break;
case OPENED:
if( f->callbacks->down )
(*f->callbacks->down)(f);
f->state = STARTING;
break;
default:
FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state));
}
}
/*
* fsm_open - Link is allowed to come up.
*/
void
fsm_open(f)
fsm *f;
{
switch( f->state ){
case INITIAL:
f->state = STARTING;
if( f->callbacks->starting )
(*f->callbacks->starting)(f);
break;
case CLOSED:
if( f->flags & OPT_SILENT )
f->state = STOPPED;
else {
/* Send an initial configure-request */
fsm_sconfreq(f, 0);
f->state = REQSENT;
}
break;
case CLOSING:
f->state = STOPPING;
/* fall through */
case STOPPED:
case OPENED:
if( f->flags & OPT_RESTART ){
fsm_lowerdown(f);
fsm_lowerup(f);
}
break;
}
}
/*
* terminate_layer - Start process of shutting down the FSM
*
* Cancel any timeout running, notify upper layers we're done, and
* send a terminate-request message as configured.
*/
static void
terminate_layer(f, nextstate)
fsm *f;
int nextstate;
{
if( f->state != OPENED )
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
else if( f->callbacks->down )
(*f->callbacks->down)(f); /* Inform upper layers we're down */
/* Init restart counter and send Terminate-Request */
f->retransmits = f->maxtermtransmits;
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
if (f->retransmits == 0) {
/*
* User asked for no terminate requests at all; just close it.
* We've already fired off one Terminate-Request just to be nice
* to the peer, but we're not going to wait for a reply.
*/
f->state = nextstate == CLOSING ? CLOSED : STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
return;
}
TIMEOUT(fsm_timeout, f, f->timeouttime);
--f->retransmits;
f->state = nextstate;
}
/*
* fsm_close - Start closing connection.
*
* Cancel timeouts and either initiate close or possibly go directly to
* the CLOSED state.
*/
void
fsm_close(f, reason)
fsm *f;
char *reason;
{
f->term_reason = reason;
f->term_reason_len = (reason == NULL? 0: strlen(reason));
switch( f->state ){
case STARTING:
f->state = INITIAL;
break;
case STOPPED:
f->state = CLOSED;
break;
case STOPPING:
f->state = CLOSING;
break;
case REQSENT:
case ACKRCVD:
case ACKSENT:
case OPENED:
terminate_layer(f, CLOSING);
break;
}
}
/*
* fsm_timeout - Timeout expired.
*/
static void
fsm_timeout(arg)
void *arg;
{
fsm *f = (fsm *) arg;
switch (f->state) {
case CLOSING:
case STOPPING:
if( f->retransmits <= 0 ){
/*
* We've waited for an ack long enough. Peer probably heard us.
*/
f->state = (f->state == CLOSING)? CLOSED: STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
} else {
/* Send Terminate-Request */
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
(u_char *) f->term_reason, f->term_reason_len);
TIMEOUT(fsm_timeout, f, f->timeouttime);
--f->retransmits;
}
break;
case REQSENT:
case ACKRCVD:
case ACKSENT:
if (f->retransmits <= 0) {
warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f));
f->state = STOPPED;
if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
(*f->callbacks->finished)(f);
} else {
/* Retransmit the configure-request */
if (f->callbacks->retransmit)
(*f->callbacks->retransmit)(f);
fsm_sconfreq(f, 1); /* Re-send Configure-Request */
if( f->state == ACKRCVD )
f->state = REQSENT;
}
break;
default:
FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state));
}
}
/*
* fsm_input - Input packet.
*/
void
fsm_input(f, inpacket, l)
fsm *f;
u_char *inpacket;
int l;
{
u_char *inp;
u_char code, id;
int len;
/*
* Parse header (code, id and length).
* If packet too short, drop it.
*/
inp = inpacket;
if (l < HEADERLEN) {
FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
GETSHORT(len, inp);
if (len < HEADERLEN) {
FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol));
return;
}
if (len > l) {
FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol));
return;
}
len -= HEADERLEN; /* subtract header length */
if( f->state == INITIAL || f->state == STARTING ){
FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.",
f->protocol, f->state));
return;
}
/*
* Action depends on code.
*/
switch (code) {
case CONFREQ:
fsm_rconfreq(f, id, inp, len);
break;
case CONFACK:
fsm_rconfack(f, id, inp, len);
break;
case CONFNAK:
case CONFREJ:
fsm_rconfnakrej(f, code, id, inp, len);
break;
case TERMREQ:
fsm_rtermreq(f, id, inp, len);
break;
case TERMACK:
fsm_rtermack(f);
break;
case CODEREJ:
fsm_rcoderej(f, inp, len);
break;
default:
if( !f->callbacks->extcode
|| !(*f->callbacks->extcode)(f, code, id, inp, len) )
fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
break;
}
}
/*
* fsm_rconfreq - Receive Configure-Request.
*/
static void
fsm_rconfreq(f, id, inp, len)
fsm *f;
u_char id;
u_char *inp;
int len;
{
int code, reject_if_disagree;
switch( f->state ){
case CLOSED:
/* Go away, we're closed */
fsm_sdata(f, TERMACK, id, NULL, 0);
return;
case CLOSING:
case STOPPING:
return;
case OPENED:
/* Go down and restart negotiation */
if( f->callbacks->down )
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
case STOPPED:
/* Negotiation started by our peer */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
/*
* Pass the requested configuration options
* to protocol-specific code for checking.
*/
if (f->callbacks->reqci){ /* Check CI */
reject_if_disagree = (f->nakloops >= f->maxnakloops);
code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
} else if (len)
code = CONFREJ; /* Reject all CI */
else
code = CONFACK;
/* send the Ack, Nak or Rej to the peer */
fsm_sdata(f, code, id, inp, len);
if (code == CONFACK) {
if (f->state == ACKRCVD) {
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
f->state = OPENED;
if (f->callbacks->up)
(*f->callbacks->up)(f); /* Inform upper layers */
} else
f->state = ACKSENT;
f->nakloops = 0;
} else {
/* we sent CONFACK or CONFREJ */
if (f->state != ACKRCVD)
f->state = REQSENT;
if( code == CONFNAK )
++f->nakloops;
}
}
/*
* fsm_rconfack - Receive Configure-Ack.
*/
static void
fsm_rconfack(f, id, inp, len)
fsm *f;
int id;
u_char *inp;
int len;
{
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
(len == 0)) ){
/* Ack is bad - ignore it */
error("Received bad configure-ack: %P", inp, len);
return;
}
f->seen_ack = 1;
f->rnakloops = 0;
switch (f->state) {
case CLOSED:
case STOPPED:
fsm_sdata(f, TERMACK, id, NULL, 0);
break;
case REQSENT:
f->state = ACKRCVD;
f->retransmits = f->maxconfreqtransmits;
break;
case ACKRCVD:
/* Huh? an extra valid Ack? oh well... */
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
case ACKSENT:
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
f->state = OPENED;
f->retransmits = f->maxconfreqtransmits;
if (f->callbacks->up)
(*f->callbacks->up)(f); /* Inform upper layers */
break;
case OPENED:
/* Go down and restart negotiation */
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
}
/*
* fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
*/
static void
fsm_rconfnakrej(f, code, id, inp, len)
fsm *f;
int code, id;
u_char *inp;
int len;
{
int ret;
int treat_as_reject;
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
if (code == CONFNAK) {
++f->rnakloops;
treat_as_reject = (f->rnakloops >= f->maxnakloops);
if (f->callbacks->nakci == NULL
|| !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) {
error("Received bad configure-nak: %P", inp, len);
return;
}
} else {
f->rnakloops = 0;
if (f->callbacks->rejci == NULL
|| !(ret = f->callbacks->rejci(f, inp, len))) {
error("Received bad configure-rej: %P", inp, len);
return;
}
}
f->seen_ack = 1;
switch (f->state) {
case CLOSED:
case STOPPED:
fsm_sdata(f, TERMACK, id, NULL, 0);
break;
case REQSENT:
case ACKSENT:
/* They didn't agree to what we wanted - try another request */
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
if (ret < 0)
f->state = STOPPED; /* kludge for stopping CCP */
else
fsm_sconfreq(f, 0); /* Send Configure-Request */
break;
case ACKRCVD:
/* Got a Nak/reject when we had already had an Ack?? oh well... */
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
case OPENED:
/* Go down and restart negotiation */
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
f->state = REQSENT;
break;
}
}
/*
* fsm_rtermreq - Receive Terminate-Req.
*/
static void
fsm_rtermreq(f, id, p, len)
fsm *f;
int id;
u_char *p;
int len;
{
switch (f->state) {
case ACKRCVD:
case ACKSENT:
f->state = REQSENT; /* Start over but keep trying */
break;
case OPENED:
if (len > 0) {
info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p);
} else
info("%s terminated by peer", PROTO_NAME(f));
f->retransmits = 0;
f->state = STOPPING;
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
TIMEOUT(fsm_timeout, f, f->timeouttime);
break;
}
fsm_sdata(f, TERMACK, id, NULL, 0);
}
/*
* fsm_rtermack - Receive Terminate-Ack.
*/
static void
fsm_rtermack(f)
fsm *f;
{
switch (f->state) {
case CLOSING:
UNTIMEOUT(fsm_timeout, f);
f->state = CLOSED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case STOPPING:
UNTIMEOUT(fsm_timeout, f);
f->state = STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case ACKRCVD:
f->state = REQSENT;
break;
case OPENED:
if (f->callbacks->down)
(*f->callbacks->down)(f); /* Inform upper layers */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
}
}
/*
* fsm_rcoderej - Receive an Code-Reject.
*/
static void
fsm_rcoderej(f, inp, len)
fsm *f;
u_char *inp;
int len;
{
u_char code, id;
if (len < HEADERLEN) {
FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!"));
return;
}
GETCHAR(code, inp);
GETCHAR(id, inp);
warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id);
if( f->state == ACKRCVD )
f->state = REQSENT;
}
/*
* fsm_protreject - Peer doesn't speak this protocol.
*
* Treat this as a catastrophic error (RXJ-).
*/
void
fsm_protreject(f)
fsm *f;
{
switch( f->state ){
case CLOSING:
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
/* fall through */
case CLOSED:
f->state = CLOSED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case STOPPING:
case REQSENT:
case ACKRCVD:
case ACKSENT:
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
/* fall through */
case STOPPED:
f->state = STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case OPENED:
terminate_layer(f, STOPPING);
break;
default:
FSMDEBUG(("%s: Protocol-reject event in state %d!",
PROTO_NAME(f), f->state));
}
}
/*
* fsm_sconfreq - Send a Configure-Request.
*/
static void
fsm_sconfreq(f, retransmit)
fsm *f;
int retransmit;
{
u_char *outp;
int cilen;
if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
/* Not currently negotiating - reset options */
if( f->callbacks->resetci )
(*f->callbacks->resetci)(f);
f->nakloops = 0;
f->rnakloops = 0;
}
if( !retransmit ){
/* New request - reset retransmission counter, use new ID */
f->retransmits = f->maxconfreqtransmits;
f->reqid = ++f->id;
}
f->seen_ack = 0;
/*
* Make up the request packet
*/
outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
if( f->callbacks->cilen && f->callbacks->addci ){
cilen = (*f->callbacks->cilen)(f);
if( cilen > peer_mru[f->unit] - HEADERLEN )
cilen = peer_mru[f->unit] - HEADERLEN;
if (f->callbacks->addci)
(*f->callbacks->addci)(f, outp, &cilen);
} else
cilen = 0;
/* send the request to our peer */
fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
/* start the retransmit timer */
--f->retransmits;
TIMEOUT(fsm_timeout, f, f->timeouttime);
}
/*
* fsm_sdata - Send some data.
*
* Used for all packets sent to our peer by this module.
*/
void
fsm_sdata(f, code, id, data, datalen)
fsm *f;
u_char code, id;
u_char *data;
int datalen;
{
u_char *outp;
int outlen;
/* Adjust length to be smaller than MTU */
outp = outpacket_buf;
if (datalen > peer_mru[f->unit] - HEADERLEN)
datalen = peer_mru[f->unit] - HEADERLEN;
if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
outlen = datalen + HEADERLEN;
MAKEHEADER(outp, f->protocol);
PUTCHAR(code, outp);
PUTCHAR(id, outp);
PUTSHORT(outlen, outp);
output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
}

168
pppd/fsm.h Normal file
View File

@ -0,0 +1,168 @@
/*
* fsm.h - {Link, IP} Control Protocol Finite State Machine definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $
*/
/*
* Packet header = Code, id, length.
*/
#define HEADERLEN 4
/*
* CP (LCP, IPCP, etc.) codes.
*/
#define CONFREQ 1 /* Configuration Request */
#define CONFACK 2 /* Configuration Ack */
#define CONFNAK 3 /* Configuration Nak */
#define CONFREJ 4 /* Configuration Reject */
#define TERMREQ 5 /* Termination Request */
#define TERMACK 6 /* Termination Ack */
#define CODEREJ 7 /* Code Reject */
/*
* Each FSM is described by an fsm structure and fsm callbacks.
*/
typedef struct fsm {
int unit; /* Interface unit number */
int protocol; /* Data Link Layer Protocol field value */
int state; /* State */
int flags; /* Contains option bits */
u_char id; /* Current id */
u_char reqid; /* Current request id */
u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */
int timeouttime; /* Timeout time in milliseconds */
int maxconfreqtransmits; /* Maximum Configure-Request transmissions */
int retransmits; /* Number of retransmissions left */
int maxtermtransmits; /* Maximum Terminate-Request transmissions */
int nakloops; /* Number of nak loops since last ack */
int rnakloops; /* Number of naks received */
int maxnakloops; /* Maximum number of nak loops tolerated */
struct fsm_callbacks *callbacks; /* Callback routines */
char *term_reason; /* Reason for closing protocol */
int term_reason_len; /* Length of term_reason */
} fsm;
typedef struct fsm_callbacks {
void (*resetci) /* Reset our Configuration Information */
__P((fsm *));
int (*cilen) /* Length of our Configuration Information */
__P((fsm *));
void (*addci) /* Add our Configuration Information */
__P((fsm *, u_char *, int *));
int (*ackci) /* ACK our Configuration Information */
__P((fsm *, u_char *, int));
int (*nakci) /* NAK our Configuration Information */
__P((fsm *, u_char *, int, int));
int (*rejci) /* Reject our Configuration Information */
__P((fsm *, u_char *, int));
int (*reqci) /* Request peer's Configuration Information */
__P((fsm *, u_char *, int *, int));
void (*up) /* Called when fsm reaches OPENED state */
__P((fsm *));
void (*down) /* Called when fsm leaves OPENED state */
__P((fsm *));
void (*starting) /* Called when we want the lower layer */
__P((fsm *));
void (*finished) /* Called when we don't want the lower layer */
__P((fsm *));
void (*protreject) /* Called when Protocol-Reject received */
__P((int));
void (*retransmit) /* Retransmission is necessary */
__P((fsm *));
int (*extcode) /* Called when unknown code received */
__P((fsm *, int, int, u_char *, int));
char *proto_name; /* String name for protocol (for messages) */
} fsm_callbacks;
/*
* Link states.
*/
#define INITIAL 0 /* Down, hasn't been opened */
#define STARTING 1 /* Down, been opened */
#define CLOSED 2 /* Up, hasn't been opened */
#define STOPPED 3 /* Open, waiting for down event */
#define CLOSING 4 /* Terminating the connection, not open */
#define STOPPING 5 /* Terminating, but open */
#define REQSENT 6 /* We've sent a Config Request */
#define ACKRCVD 7 /* We've received a Config Ack */
#define ACKSENT 8 /* We've sent a Config Ack */
#define OPENED 9 /* Connection available */
/*
* Flags - indicate options controlling FSM operation
*/
#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
#define OPT_SILENT 4 /* Wait for peer to speak first */
/*
* Timeouts.
*/
#define DEFTIMEOUT 3 /* Timeout time in seconds */
#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
/*
* Prototypes
*/
void fsm_init __P((fsm *));
void fsm_lowerup __P((fsm *));
void fsm_lowerdown __P((fsm *));
void fsm_open __P((fsm *));
void fsm_close __P((fsm *, char *));
void fsm_input __P((fsm *, u_char *, int));
void fsm_protreject __P((fsm *));
void fsm_sdata __P((fsm *, int, int, u_char *, int));
/*
* Variables
*/
extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */

2311
pppd/ipcp.c Normal file

File diff suppressed because it is too large Load Diff

96
pppd/ipcp.h Normal file
View File

@ -0,0 +1,96 @@
/*
* ipcp.h - IP Control Protocol definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: ipcp.h,v 1.14 2002/12/04 23:03:32 paulus Exp $
*/
/*
* Options.
*/
#define CI_ADDRS 1 /* IP Addresses */
#define CI_COMPRESSTYPE 2 /* Compression Type */
#define CI_ADDR 3
#define CI_MS_DNS1 129 /* Primary DNS value */
#define CI_MS_WINS1 130 /* Primary WINS value */
#define CI_MS_DNS2 131 /* Secondary DNS value */
#define CI_MS_WINS2 132 /* Secondary WINS value */
#define MAX_STATES 16 /* from slcompress.h */
#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */
/* maxslot and slot number compression) */
#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/
#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
/* compression option*/
typedef struct ipcp_options {
bool neg_addr; /* Negotiate IP Address? */
bool old_addrs; /* Use old (IP-Addresses) option? */
bool req_addr; /* Ask peer to send IP address? */
bool default_route; /* Assign default route through interface? */
bool proxy_arp; /* Make proxy ARP entry for peer? */
bool neg_vj; /* Van Jacobson Compression? */
bool old_vj; /* use old (short) form of VJ option? */
bool accept_local; /* accept peer's value for ouraddr */
bool accept_remote; /* accept peer's value for hisaddr */
bool req_dns1; /* Ask peer to send primary DNS address? */
bool req_dns2; /* Ask peer to send secondary DNS address? */
int vj_protocol; /* protocol value to use in VJ option */
int maxslotindex; /* values for RFC1332 VJ compression neg. */
bool cflag;
u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
u_int32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */
u_int32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
} ipcp_options;
extern fsm ipcp_fsm[];
extern ipcp_options ipcp_wantoptions[];
extern ipcp_options ipcp_gotoptions[];
extern ipcp_options ipcp_allowoptions[];
extern ipcp_options ipcp_hisoptions[];
char *ip_ntoa __P((u_int32_t));
extern struct protent ipcp_protent;

1544
pppd/ipv6cp.c Normal file

File diff suppressed because it is too large Load Diff

169
pppd/ipv6cp.h Normal file
View File

@ -0,0 +1,169 @@
/*
* ipv6cp.h - PPP IPV6 Control Protocol.
*
* Copyright (c) 1999 Tommi Komulainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Tommi Komulainen
* <Tommi.Komulainen@iki.fi>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/* Original version, based on RFC2023 :
Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt,
Alain.Durand@imag.fr, IMAG,
Jean-Luc.Richier@imag.fr, IMAG-LSR.
Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE,
Alain.Durand@imag.fr, IMAG,
Jean-Luc.Richier@imag.fr, IMAG-LSR.
Ce travail a é fait au sein du GIE DYADE (Groupement d'Intérêt
Économique ayant pour membres BULL S.A. et l'INRIA).
Ce logiciel informatique est disponible aux conditions
usuelles dans la recherche, c'est-à-dire qu'il peut
être utilisé, copié, modifié, distribué à l'unique
condition que ce texte soit conservé afin que
l'origine de ce logiciel soit reconnue.
Le nom de l'Institut National de Recherche en Informatique
et en Automatique (INRIA), de l'IMAG, ou d'une personne morale
ou physique ayant participé à l'élaboration de ce logiciel ne peut
être utilisé sans son accord préalable explicite.
Ce logiciel est fourni tel quel sans aucune garantie,
support ou responsabilité d'aucune sorte.
Ce logiciel est dérivé de sources d'origine
"University of California at Berkeley" et
"Digital Equipment Corporation" couvertes par des copyrights.
L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG)
est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National
Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant
sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR).
This work has been done in the context of GIE DYADE (joint R & D venture
between BULL S.A. and INRIA).
This software is available with usual "research" terms
with the aim of retain credits of the software.
Permission to use, copy, modify and distribute this software for any
purpose and without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies,
and the name of INRIA, IMAG, or any contributor not be used in advertising
or publicity pertaining to this material without the prior explicit
permission. The software is provided "as is" without any
warranties, support or liabilities of any kind.
This software is derived from source code from
"University of California at Berkeley" and
"Digital Equipment Corporation" protected by copyrights.
Grenoble's Institute of Computer Science and Applied Mathematics (IMAG)
is a federation of seven research units funded by the CNRS, National
Polytechnic Institute of Grenoble and University Joseph Fourier.
The research unit in Software, Systems, Networks (LSR) is member of IMAG.
*/
/*
* Derived from :
*
*
* ipcp.h - IP Control Protocol definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: ipv6cp.h,v 1.7 2002/12/04 23:03:32 paulus Exp $
*/
/*
* Options.
*/
#define CI_IFACEID 1 /* Interface Identifier */
#define CI_COMPRESSTYPE 2 /* Compression Type */
/* No compression types yet defined.
*#define IPV6CP_COMP 0x004f
*/
typedef struct ipv6cp_options {
int neg_ifaceid; /* Negotiate interface identifier? */
int req_ifaceid; /* Ask peer to send interface identifier? */
int accept_local; /* accept peer's value for iface id? */
int opt_local; /* ourtoken set by option */
int opt_remote; /* histoken set by option */
int use_ip; /* use IP as interface identifier */
int use_persistent; /* use uniquely persistent value for address */
int neg_vj; /* Van Jacobson Compression? */
u_short vj_protocol; /* protocol value to use in VJ option */
eui64_t ourid, hisid; /* Interface identifiers */
} ipv6cp_options;
extern fsm ipv6cp_fsm[];
extern ipv6cp_options ipv6cp_wantoptions[];
extern ipv6cp_options ipv6cp_gotoptions[];
extern ipv6cp_options ipv6cp_allowoptions[];
extern ipv6cp_options ipv6cp_hisoptions[];
extern struct protent ipv6cp_protent;

1598
pppd/ipxcp.c Normal file

File diff suppressed because it is too large Load Diff

94
pppd/ipxcp.h Normal file
View File

@ -0,0 +1,94 @@
/*
* ipxcp.h - IPX Control Protocol definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: ipxcp.h,v 1.5 2002/12/04 23:03:32 paulus Exp $
*/
/*
* Options.
*/
#define IPX_NETWORK_NUMBER 1 /* IPX Network Number */
#define IPX_NODE_NUMBER 2
#define IPX_COMPRESSION_PROTOCOL 3
#define IPX_ROUTER_PROTOCOL 4
#define IPX_ROUTER_NAME 5
#define IPX_COMPLETE 6
/* Values for the router protocol */
#define IPX_NONE 0
#define RIP_SAP 2
#define NLSP 4
typedef struct ipxcp_options {
bool neg_node; /* Negotiate IPX node number? */
bool req_node; /* Ask peer to send IPX node number? */
bool neg_nn; /* Negotiate IPX network number? */
bool req_nn; /* Ask peer to send IPX network number */
bool neg_name; /* Negotiate IPX router name */
bool neg_complete; /* Negotiate completion */
bool neg_router; /* Negotiate IPX router number */
bool accept_local; /* accept peer's value for ournode */
bool accept_remote; /* accept peer's value for hisnode */
bool accept_network; /* accept network number */
bool tried_nlsp; /* I have suggested NLSP already */
bool tried_rip; /* I have suggested RIP/SAP already */
u_int32_t his_network; /* base network number */
u_int32_t our_network; /* our value for network number */
u_int32_t network; /* the final network number */
u_char his_node[6]; /* peer's node number */
u_char our_node[6]; /* our node number */
u_char name [48]; /* name of the router */
int router; /* routing protocol */
} ipxcp_options;
extern fsm ipxcp_fsm[];
extern ipxcp_options ipxcp_wantoptions[];
extern ipxcp_options ipxcp_gotoptions[];
extern ipxcp_options ipxcp_allowoptions[];
extern ipxcp_options ipxcp_hisoptions[];
extern struct protent ipxcp_protent;

2380
pppd/lcp.c Normal file

File diff suppressed because it is too large Load Diff

135
pppd/lcp.h Normal file
View File

@ -0,0 +1,135 @@
/*
* lcp.h - Link Control Protocol definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: lcp.h,v 1.20 2004/11/14 22:53:42 carlsonj Exp $
*/
/*
* Options.
*/
#define CI_VENDOR 0 /* Vendor Specific */
#define CI_MRU 1 /* Maximum Receive Unit */
#define CI_ASYNCMAP 2 /* Async Control Character Map */
#define CI_AUTHTYPE 3 /* Authentication Type */
#define CI_QUALITY 4 /* Quality Protocol */
#define CI_MAGICNUMBER 5 /* Magic Number */
#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
#define CI_FCSALTERN 9 /* FCS-Alternatives */
#define CI_SDP 10 /* Self-Describing-Pad */
#define CI_NUMBERED 11 /* Numbered-Mode */
#define CI_CALLBACK 13 /* callback */
#define CI_MRRU 17 /* max reconstructed receive unit; multilink */
#define CI_SSNHF 18 /* short sequence numbers for multilink */
#define CI_EPDISC 19 /* endpoint discriminator */
#define CI_MPPLUS 22 /* Multi-Link-Plus-Procedure */
#define CI_LDISC 23 /* Link-Discriminator */
#define CI_LCPAUTH 24 /* LCP Authentication */
#define CI_COBS 25 /* Consistent Overhead Byte Stuffing */
#define CI_PREFELIS 26 /* Prefix Elision */
#define CI_MPHDRFMT 27 /* MP Header Format */
#define CI_I18N 28 /* Internationalization */
#define CI_SDL 29 /* Simple Data Link */
/*
* LCP-specific packet types (code numbers).
*/
#define PROTREJ 8 /* Protocol Reject */
#define ECHOREQ 9 /* Echo Request */
#define ECHOREP 10 /* Echo Reply */
#define DISCREQ 11 /* Discard Request */
#define IDENTIF 12 /* Identification */
#define TIMEREM 13 /* Time Remaining */
/* Value used as data for CI_CALLBACK option */
#define CBCP_OPT 6 /* Use callback control protocol */
/*
* The state of options is described by an lcp_options structure.
*/
typedef struct lcp_options {
bool passive; /* Don't die if we don't get a response */
bool silent; /* Wait for the other end to start first */
bool restart; /* Restart vs. exit after close */
bool neg_mru; /* Negotiate the MRU? */
bool neg_asyncmap; /* Negotiate the async map? */
bool neg_upap; /* Ask for UPAP authentication? */
bool neg_chap; /* Ask for CHAP authentication? */
bool neg_eap; /* Ask for EAP authentication? */
bool neg_magicnumber; /* Ask for magic number? */
bool neg_pcompression; /* HDLC Protocol Field Compression? */
bool neg_accompression; /* HDLC Address/Control Field Compression? */
bool neg_lqr; /* Negotiate use of Link Quality Reports */
bool neg_cbcp; /* Negotiate use of CBCP */
bool neg_mrru; /* negotiate multilink MRRU */
bool neg_ssnhf; /* negotiate short sequence numbers */
bool neg_endpoint; /* negotiate endpoint discriminator */
int mru; /* Value of MRU */
int mrru; /* Value of MRRU, and multilink enable */
u_char chap_mdtype; /* which MD types (hashing algorithm) */
u_int32_t asyncmap; /* Value of async map */
u_int32_t magicnumber;
int numloops; /* Number of loops during magic number neg. */
u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */
struct epdisc endpoint; /* endpoint discriminator */
} lcp_options;
extern fsm lcp_fsm[];
extern lcp_options lcp_wantoptions[];
extern lcp_options lcp_gotoptions[];
extern lcp_options lcp_allowoptions[];
extern lcp_options lcp_hisoptions[];
#define DEFMRU 1500 /* Try for this */
#define MINMRU 128 /* No MRUs below this */
#define MAXMRU 16384 /* Normally limit MRU to this */
void lcp_open __P((int));
void lcp_close __P((int, char *));
void lcp_lowerup __P((int));
void lcp_lowerdown __P((int));
void lcp_sprotrej __P((int, u_char *, int)); /* send protocol reject */
extern struct protent lcp_protent;
/* Default number of times we receive our magic number from the peer
before deciding the link is looped-back. */
#define DEFLOOPBACKFAIL 10

123
pppd/magic.c Normal file
View File

@ -0,0 +1,123 @@
/*
* magic.c - PPP Magic Number routines.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: magic.c,v 1.11 2003/06/11 23:56:26 paulus Exp $"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include "pppd.h"
#include "magic.h"
static const char rcsid[] = RCSID;
extern long mrand48 __P((void));
extern void srand48 __P((long));
/*
* magic_init - Initialize the magic number generator.
*
* Attempts to compute a random number seed which will not repeat.
* The current method uses the current hostid, current process ID
* and current time, currently.
*/
void
magic_init()
{
long seed;
struct timeval t;
gettimeofday(&t, NULL);
seed = get_host_seed() ^ t.tv_sec ^ t.tv_usec ^ getpid();
srand48(seed);
}
/*
* magic - Returns the next magic number.
*/
u_int32_t
magic()
{
return (u_int32_t) mrand48();
}
/*
* random_bytes - Fill a buffer with random bytes.
*/
void
random_bytes(unsigned char *buf, int len)
{
int i;
for (i = 0; i < len; ++i)
buf[i] = mrand48() >> 24;
}
#ifdef NO_DRAND48
/*
* Substitute procedures for those systems which don't have
* drand48 et al.
*/
double
drand48()
{
return (double)random() / (double)0x7fffffffL; /* 2**31-1 */
}
long
mrand48()
{
return random();
}
void
srand48(seedval)
long seedval;
{
srandom((int)seedval);
}
#endif

49
pppd/magic.h Normal file
View File

@ -0,0 +1,49 @@
/*
* magic.h - PPP Magic Number definitions.
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $
*/
void magic_init __P((void)); /* Initialize the magic number generator */
u_int32_t magic __P((void)); /* Returns the next magic number */
/* Fill buffer with random bytes */
void random_bytes __P((unsigned char *buf, int len));

2226
pppd/main.c Normal file

File diff suppressed because it is too large Load Diff

299
pppd/md4.c Normal file
View File

@ -0,0 +1,299 @@
/*
** ********************************************************************
** md4.c -- Implementation of MD4 Message Digest Algorithm **
** Updated: 2/16/90 by Ronald L. Rivest **
** (C) 1990 RSA Data Security, Inc. **
** ********************************************************************
*/
/*
** To use MD4:
** -- Include md4.h in your program
** -- Declare an MDstruct MD to hold the state of the digest
** computation.
** -- Initialize MD using MDbegin(&MD)
** -- For each full block (64 bytes) X you wish to process, call
** MD4Update(&MD,X,512)
** (512 is the number of bits in a full block.)
** -- For the last block (less than 64 bytes) you wish to process,
** MD4Update(&MD,X,n)
** where n is the number of bits in the partial block. A partial
** block terminates the computation, so every MD computation
** should terminate by processing a partial block, even if it
** has n = 0.
** -- The message digest is available in MD.buffer[0] ...
** MD.buffer[3]. (Least-significant byte of each word
** should be output first.)
** -- You can print out the digest using MDprint(&MD)
*/
/* Implementation notes:
** This implementation assumes that ints are 32-bit quantities.
*/
#define TRUE 1
#define FALSE 0
/* Compile-time includes
*/
#include <stdio.h>
#include "md4.h"
#include "pppd.h"
/* Compile-time declarations of MD4 "magic constants".
*/
#define I0 0x67452301 /* Initial values for MD buffer */
#define I1 0xefcdab89
#define I2 0x98badcfe
#define I3 0x10325476
#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
** Table 2, page 660.
*/
#define fs1 3 /* round 1 shift amounts */
#define fs2 7
#define fs3 11
#define fs4 19
#define gs1 3 /* round 2 shift amounts */
#define gs2 5
#define gs3 9
#define gs4 13
#define hs1 3 /* round 3 shift amounts */
#define hs2 9
#define hs3 11
#define hs4 15
/* Compile-time macro declarations for MD4.
** Note: The "rot" operator uses the variable "tmp".
** It assumes tmp is declared as unsigned int, so that the >>
** operator will shift in zeros rather than extending the sign bit.
*/
#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
#define h(X,Y,Z) (X^Y^Z)
#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
/* MD4print(MDp)
** Print message digest buffer MDp as 32 hexadecimal digits.
** Order is from low-order byte of buffer[0] to high-order byte of
** buffer[3].
** Each byte is printed with high-order hexadecimal digit first.
** This is a user-callable routine.
*/
void
MD4Print(MDp)
MD4_CTX *MDp;
{
int i,j;
for (i=0;i<4;i++)
for (j=0;j<32;j=j+8)
printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
}
/* MD4Init(MDp)
** Initialize message digest buffer MDp.
** This is a user-callable routine.
*/
void
MD4Init(MDp)
MD4_CTX *MDp;
{
int i;
MDp->buffer[0] = I0;
MDp->buffer[1] = I1;
MDp->buffer[2] = I2;
MDp->buffer[3] = I3;
for (i=0;i<8;i++) MDp->count[i] = 0;
MDp->done = 0;
}
/* MDblock(MDp,X)
** Update message digest buffer MDp->buffer using 16-word data block X.
** Assumes all 16 words of X are full of data.
** Does not update MDp->count.
** This routine is not user-callable.
*/
static void
MDblock(MDp,Xb)
MD4_CTX *MDp;
unsigned char *Xb;
{
register unsigned int tmp, A, B, C, D;
unsigned int X[16];
int i;
for (i = 0; i < 16; ++i) {
X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24);
Xb += 4;
}
A = MDp->buffer[0];
B = MDp->buffer[1];
C = MDp->buffer[2];
D = MDp->buffer[3];
/* Update the message digest buffer */
ff(A , B , C , D , 0 , fs1); /* Round 1 */
ff(D , A , B , C , 1 , fs2);
ff(C , D , A , B , 2 , fs3);
ff(B , C , D , A , 3 , fs4);
ff(A , B , C , D , 4 , fs1);
ff(D , A , B , C , 5 , fs2);
ff(C , D , A , B , 6 , fs3);
ff(B , C , D , A , 7 , fs4);
ff(A , B , C , D , 8 , fs1);
ff(D , A , B , C , 9 , fs2);
ff(C , D , A , B , 10 , fs3);
ff(B , C , D , A , 11 , fs4);
ff(A , B , C , D , 12 , fs1);
ff(D , A , B , C , 13 , fs2);
ff(C , D , A , B , 14 , fs3);
ff(B , C , D , A , 15 , fs4);
gg(A , B , C , D , 0 , gs1); /* Round 2 */
gg(D , A , B , C , 4 , gs2);
gg(C , D , A , B , 8 , gs3);
gg(B , C , D , A , 12 , gs4);
gg(A , B , C , D , 1 , gs1);
gg(D , A , B , C , 5 , gs2);
gg(C , D , A , B , 9 , gs3);
gg(B , C , D , A , 13 , gs4);
gg(A , B , C , D , 2 , gs1);
gg(D , A , B , C , 6 , gs2);
gg(C , D , A , B , 10 , gs3);
gg(B , C , D , A , 14 , gs4);
gg(A , B , C , D , 3 , gs1);
gg(D , A , B , C , 7 , gs2);
gg(C , D , A , B , 11 , gs3);
gg(B , C , D , A , 15 , gs4);
hh(A , B , C , D , 0 , hs1); /* Round 3 */
hh(D , A , B , C , 8 , hs2);
hh(C , D , A , B , 4 , hs3);
hh(B , C , D , A , 12 , hs4);
hh(A , B , C , D , 2 , hs1);
hh(D , A , B , C , 10 , hs2);
hh(C , D , A , B , 6 , hs3);
hh(B , C , D , A , 14 , hs4);
hh(A , B , C , D , 1 , hs1);
hh(D , A , B , C , 9 , hs2);
hh(C , D , A , B , 5 , hs3);
hh(B , C , D , A , 13 , hs4);
hh(A , B , C , D , 3 , hs1);
hh(D , A , B , C , 11 , hs2);
hh(C , D , A , B , 7 , hs3);
hh(B , C , D , A , 15 , hs4);
MDp->buffer[0] += A;
MDp->buffer[1] += B;
MDp->buffer[2] += C;
MDp->buffer[3] += D;
}
/* MD4Update(MDp,X,count)
** Input: X -- a pointer to an array of unsigned characters.
** count -- the number of bits of X to use.
** (if not a multiple of 8, uses high bits of last byte.)
** Update MDp using the number of bits of X given by count.
** This is the basic input routine for an MD4 user.
** The routine completes the MD computation when count < 512, so
** every MD computation should end with one call to MD4Update with a
** count less than 512. A call with count 0 will be ignored if the
** MD has already been terminated (done != 0), so an extra call with
** count 0 can be given as a "courtesy close" to force termination
** if desired.
*/
void
MD4Update(MDp,X,count)
MD4_CTX *MDp;
unsigned char *X;
unsigned int count;
{
unsigned int i, tmp, bit, byte, mask;
unsigned char XX[64];
unsigned char *p;
/* return with no error if this is a courtesy close with count
** zero and MDp->done is true.
*/
if (count == 0 && MDp->done) return;
/* check to see if MD is already done and report error */
if (MDp->done)
{ printf("\nError: MD4Update MD already done."); return; }
/* Add count to MDp->count */
tmp = count;
p = MDp->count;
while (tmp)
{ tmp += *p;
*p++ = tmp;
tmp = tmp >> 8;
}
/* Process data */
if (count == 512)
{ /* Full block of data to handle */
MDblock(MDp,X);
}
else if (count > 512) /* Check for count too large */
{
printf("\nError: MD4Update called with illegal count value %d.",
count);
return;
}
else /* partial block -- must be last block so finish up */
{
/* Find out how many bytes and residual bits there are */
byte = count >> 3;
bit = count & 7;
/* Copy X into XX since we need to modify it */
if (count)
for (i=0;i<=byte;i++) XX[i] = X[i];
for (i=byte+1;i<64;i++) XX[i] = 0;
/* Add padding '1' bit and low-order zeros in last byte */
mask = 1 << (7 - bit);
XX[byte] = (XX[byte] | mask) & ~( mask - 1);
/* If room for bit count, finish up with this block */
if (byte <= 55)
{
for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
MDblock(MDp,XX);
}
else /* need to do two blocks to finish up */
{
MDblock(MDp,XX);
for (i=0;i<56;i++) XX[i] = 0;
for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
MDblock(MDp,XX);
}
/* Set flag saying we're done with MD computation */
MDp->done = 1;
}
}
/*
** Finish up MD4 computation and return message digest.
*/
void
MD4Final(buf, MD)
unsigned char *buf;
MD4_CTX *MD;
{
int i, j;
unsigned int w;
MD4Update(MD, NULL, 0);
for (i = 0; i < 4; ++i) {
w = MD->buffer[i];
for (j = 0; j < 4; ++j) {
*buf++ = w;
w >>= 8;
}
}
}
/*
** End of md4.c
****************************(cut)***********************************/

64
pppd/md4.h Normal file
View File

@ -0,0 +1,64 @@
/*
** ********************************************************************
** md4.h -- Header file for implementation of **
** MD4 Message Digest Algorithm **
** Updated: 2/13/90 by Ronald L. Rivest **
** (C) 1990 RSA Data Security, Inc. **
** ********************************************************************
*/
#ifndef __P
# if defined(__STDC__) || defined(__GNUC__)
# define __P(x) x
# else
# define __P(x) ()
# endif
#endif
/* MDstruct is the data structure for a message digest computation.
*/
typedef struct {
unsigned int buffer[4]; /* Holds 4-word result of MD computation */
unsigned char count[8]; /* Number of bits processed so far */
unsigned int done; /* Nonzero means MD computation finished */
} MD4_CTX;
/* MD4Init(MD4_CTX *)
** Initialize the MD4_CTX prepatory to doing a message digest
** computation.
*/
extern void MD4Init __P((MD4_CTX *MD));
/* MD4Update(MD,X,count)
** Input: X -- a pointer to an array of unsigned characters.
** count -- the number of bits of X to use (an unsigned int).
** Updates MD using the first "count" bits of X.
** The array pointed to by X is not modified.
** If count is not a multiple of 8, MD4Update uses high bits of
** last byte.
** This is the basic input routine for a user.
** The routine terminates the MD computation when count < 512, so
** every MD computation should end with one call to MD4Update with a
** count less than 512. Zero is OK for a count.
*/
extern void MD4Update __P((MD4_CTX *MD, unsigned char *X, unsigned int count));
/* MD4Print(MD)
** Prints message digest buffer MD as 32 hexadecimal digits.
** Order is from low-order byte of buffer[0] to high-order byte
** of buffer[3].
** Each byte is printed with high-order hexadecimal digit first.
*/
extern void MD4Print __P((MD4_CTX *));
/* MD4Final(buf, MD)
** Returns message digest from MD and terminates the message
** digest computation.
*/
extern void MD4Final __P((unsigned char *, MD4_CTX *));
/*
** End of md4.h
****************************(cut)***********************************/

307
pppd/md5.c Normal file
View File

@ -0,0 +1,307 @@
/*
***********************************************************************
** md5.c -- the source code for MD5 routines **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
***********************************************************************
*/
/*
***********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
***********************************************************************
*/
#include <string.h>
#include "md5.h"
/*
***********************************************************************
** Message-digest routines: **
** To form the message digest for a message M **
** (1) Initialize a context buffer mdContext using MD5_Init **
** (2) Call MD5_Update on mdContext and M **
** (3) Call MD5_Final on mdContext **
** The message digest is now in mdContext->digest[0...15] **
***********************************************************************
*/
/* forward declaration */
static void Transform (UINT4 *buf, UINT4 *in);
static unsigned char PADDING[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* F, G, H and I are basic MD5 functions */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
{(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) \
{(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#ifdef __STDC__
#define UL(x) x##U
#else
#define UL(x) x
#endif
/* The routine MD5_Init initializes the message-digest context
mdContext. All fields are set to zero.
*/
void MD5_Init (mdContext)
MD5_CTX *mdContext;
{
mdContext->i[0] = mdContext->i[1] = (UINT4)0;
/* Load magic initialization constants.
*/
mdContext->buf[0] = (UINT4)0x67452301;
mdContext->buf[1] = (UINT4)0xefcdab89;
mdContext->buf[2] = (UINT4)0x98badcfe;
mdContext->buf[3] = (UINT4)0x10325476;
}
/* The routine MD5Update updates the message-digest context to
account for the presence of each of the characters inBuf[0..inLen-1]
in the message whose digest is being computed.
*/
void MD5_Update (mdContext, inBuf, inLen)
MD5_CTX *mdContext;
unsigned char *inBuf;
unsigned int inLen;
{
UINT4 in[16];
int mdi;
unsigned int i, ii;
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* update number of bits */
if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
mdContext->i[1]++;
mdContext->i[0] += ((UINT4)inLen << 3);
mdContext->i[1] += ((UINT4)inLen >> 29);
while (inLen--) {
/* add new character to buffer, increment mdi */
mdContext->in[mdi++] = *inBuf++;
/* transform if necessary */
if (mdi == 0x40) {
for (i = 0, ii = 0; i < 16; i++, ii += 4)
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
(((UINT4)mdContext->in[ii+2]) << 16) |
(((UINT4)mdContext->in[ii+1]) << 8) |
((UINT4)mdContext->in[ii]);
Transform (mdContext->buf, in);
mdi = 0;
}
}
}
/* The routine MD5Final terminates the message-digest computation and
ends with the desired message digest in mdContext->digest[0...15].
*/
void MD5_Final (hash, mdContext)
unsigned char hash[];
MD5_CTX *mdContext;
{
UINT4 in[16];
int mdi;
unsigned int i, ii;
unsigned int padLen;
/* save number of bits */
in[14] = mdContext->i[0];
in[15] = mdContext->i[1];
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* pad out to 56 mod 64 */
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
MD5_Update (mdContext, PADDING, padLen);
/* append length in bits and transform */
for (i = 0, ii = 0; i < 14; i++, ii += 4)
in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
(((UINT4)mdContext->in[ii+2]) << 16) |
(((UINT4)mdContext->in[ii+1]) << 8) |
((UINT4)mdContext->in[ii]);
Transform (mdContext->buf, in);
/* store buffer in digest */
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
mdContext->digest[ii+1] =
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
mdContext->digest[ii+2] =
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
mdContext->digest[ii+3] =
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
}
memcpy(hash, mdContext->digest, 16);
}
/* Basic MD5 step. Transforms buf based on in.
*/
static void Transform (buf, in)
UINT4 *buf;
UINT4 *in;
{
UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
/* Round 2 */
#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
/* Round 3 */
#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
/* Round 4 */
#define S41 6
#define S42 10
#define S43 15
#define S44 21
II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
***********************************************************************
** End of md5.c **
******************************** (cut) ********************************
*/

65
pppd/md5.h Normal file
View File

@ -0,0 +1,65 @@
/*
***********************************************************************
** md5.h -- header file for implementation of MD5 **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
** Created: 2/17/90 RLR **
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
** Revised (for MD5): RLR 4/27/91 **
** -- G modified to have y&~z instead of y&z **
** -- FF, GG, HH modified to add in last register done **
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
** -- distinct additive constant for each step **
** -- round 4 added, working mod 7 **
***********************************************************************
*/
/*
***********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
***********************************************************************
*/
#ifndef __MD5_INCLUDE__
/* typedef a 32-bit type */
#ifdef _LP64
typedef unsigned int UINT4;
typedef int INT4;
#else
typedef unsigned long UINT4;
typedef long INT4;
#endif
#define _UINT4_T
/* Data structure for MD5 (Message-Digest) computation */
typedef struct {
UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
UINT4 buf[4]; /* scratch buffer */
unsigned char in[64]; /* input buffer */
unsigned char digest[16]; /* actual digest after MD5Final call */
} MD5_CTX;
void MD5_Init (MD5_CTX *mdContext);
void MD5_Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen);
void MD5_Final (unsigned char hash[], MD5_CTX *mdContext);
#define __MD5_INCLUDE__
#endif /* __MD5_INCLUDE__ */

121
pppd/mppe.h Normal file
View File

@ -0,0 +1,121 @@
/*
* mppe.h - Definitions for MPPE
*
* Copyright (c) 2008 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define MPPE_PAD 4 /* MPPE growth per frame */
#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */
/* option bits for ccp_options.mppe */
#define MPPE_OPT_40 0x01 /* 40 bit */
#define MPPE_OPT_128 0x02 /* 128 bit */
#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */
/* unsupported opts */
#define MPPE_OPT_56 0x08 /* 56 bit */
#define MPPE_OPT_MPPC 0x10 /* MPPC compression */
#define MPPE_OPT_D 0x20 /* Unknown */
#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */
/*
* This is not nice ... the alternative is a bitfield struct though.
* And unfortunately, we cannot share the same bits for the option
* names above since C and H are the same bit. We could do a u_int32
* but then we have to do a htonl() all the time and/or we still need
* to know which octet is which.
*/
#define MPPE_C_BIT 0x01 /* MPPC */
#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */
#define MPPE_L_BIT 0x20 /* 40-bit */
#define MPPE_S_BIT 0x40 /* 128-bit */
#define MPPE_M_BIT 0x80 /* 56-bit, not supported */
#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */
/* Does not include H bit; used for least significant octet only. */
#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
/* Build a CI from mppe opts (see RFC 3078) */
#define MPPE_OPTS_TO_CI(opts, ci) \
do { \
u_char *ptr = ci; /* u_char[4] */ \
\
/* H bit */ \
if (opts & MPPE_OPT_STATEFUL) \
*ptr++ = 0x0; \
else \
*ptr++ = MPPE_H_BIT; \
*ptr++ = 0; \
*ptr++ = 0; \
\
/* S,L bits */ \
*ptr = 0; \
if (opts & MPPE_OPT_128) \
*ptr |= MPPE_S_BIT; \
if (opts & MPPE_OPT_40) \
*ptr |= MPPE_L_BIT; \
/* M,D,C bits not supported */ \
} while (/* CONSTCOND */ 0)
/* The reverse of the above */
#define MPPE_CI_TO_OPTS(ci, opts) \
do { \
u_char *ptr = ci; /* u_char[4] */ \
\
opts = 0; \
\
/* H bit */ \
if (!(ptr[0] & MPPE_H_BIT)) \
opts |= MPPE_OPT_STATEFUL; \
\
/* S,L bits */ \
if (ptr[3] & MPPE_S_BIT) \
opts |= MPPE_OPT_128; \
if (ptr[3] & MPPE_L_BIT) \
opts |= MPPE_OPT_40; \
\
/* M,D,C bits */ \
if (ptr[3] & MPPE_M_BIT) \
opts |= MPPE_OPT_56; \
if (ptr[3] & MPPE_D_BIT) \
opts |= MPPE_OPT_D; \
if (ptr[3] & MPPE_C_BIT) \
opts |= MPPE_OPT_MPPC; \
\
/* Other bits */ \
if (ptr[0] & ~MPPE_H_BIT) \
opts |= MPPE_OPT_UNKNOWN; \
if (ptr[1] || ptr[2]) \
opts |= MPPE_OPT_UNKNOWN; \
if (ptr[3] & ~MPPE_ALL_BITS) \
opts |= MPPE_OPT_UNKNOWN; \
} while (/* CONSTCOND */ 0)

592
pppd/multilink.c Normal file
View File

@ -0,0 +1,592 @@
/*
* multilink.c - support routines for multilink.
*
* Copyright (c) 2000-2002 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <netinet/in.h>
#include <unistd.h>
#include "pppd.h"
#include "fsm.h"
#include "lcp.h"
#include "tdb.h"
bool endpoint_specified; /* user gave explicit endpoint discriminator */
char *bundle_id; /* identifier for our bundle */
char *blinks_id; /* key for the list of links */
bool doing_multilink; /* multilink was enabled and agreed to */
bool multilink_master; /* we own the multilink bundle */
extern TDB_CONTEXT *pppdb;
extern char db_key[];
static void make_bundle_links __P((int append));
static void remove_bundle_link __P((void));
static void iterate_bundle_links __P((void (*func) __P((char *))));
static int get_default_epdisc __P((struct epdisc *));
static int parse_num __P((char *str, const char *key, int *valp));
static int owns_unit __P((TDB_DATA pid, int unit));
#define set_ip_epdisc(ep, addr) do { \
ep->length = 4; \
ep->value[0] = addr >> 24; \
ep->value[1] = addr >> 16; \
ep->value[2] = addr >> 8; \
ep->value[3] = addr; \
} while (0)
#define LOCAL_IP_ADDR(addr) \
(((addr) & 0xff000000) == 0x0a000000 /* 10.x.x.x */ \
|| ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \
|| ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */
#define process_exists(n) (kill((n), 0) == 0 || errno != ESRCH)
void
mp_check_options()
{
lcp_options *wo = &lcp_wantoptions[0];
lcp_options *ao = &lcp_allowoptions[0];
doing_multilink = 0;
if (!multilink)
return;
/* if we're doing multilink, we have to negotiate MRRU */
if (!wo->neg_mrru) {
/* mrru not specified, default to mru */
wo->mrru = wo->mru;
wo->neg_mrru = 1;
}
ao->mrru = ao->mru;
ao->neg_mrru = 1;
if (!wo->neg_endpoint && !noendpoint) {
/* get a default endpoint value */
wo->neg_endpoint = get_default_epdisc(&wo->endpoint);
}
}
/*
* Make a new bundle or join us to an existing bundle
* if we are doing multilink.
*/
int
mp_join_bundle()
{
lcp_options *go = &lcp_gotoptions[0];
lcp_options *ho = &lcp_hisoptions[0];
lcp_options *ao = &lcp_allowoptions[0];
int unit, pppd_pid;
int l, mtu;
char *p;
TDB_DATA key, pid, rec;
if (doing_multilink) {
/* have previously joined a bundle */
if (!go->neg_mrru || !ho->neg_mrru) {
notice("oops, didn't get multilink on renegotiation");
lcp_close(0, "multilink required");
return 0;
}
/* XXX should check the peer_authname and ho->endpoint
are the same as previously */
return 0;
}
if (!go->neg_mrru || !ho->neg_mrru) {
/* not doing multilink */
if (go->neg_mrru)
notice("oops, multilink negotiated only for receive");
mtu = ho->neg_mru? ho->mru: PPP_MRU;
if (mtu > ao->mru)
mtu = ao->mru;
if (demand) {
/* already have a bundle */
cfg_bundle(0, 0, 0, 0);
netif_set_mtu(0, mtu);
return 0;
}
make_new_bundle(0, 0, 0, 0);
set_ifunit(1);
netif_set_mtu(0, mtu);
return 0;
}
doing_multilink = 1;
/*
* Find the appropriate bundle or join a new one.
* First we make up a name for the bundle.
* The length estimate is worst-case assuming every
* character has to be quoted.
*/
l = 4 * strlen(peer_authname) + 10;
if (ho->neg_endpoint)
l += 3 * ho->endpoint.length + 8;
if (bundle_name)
l += 3 * strlen(bundle_name) + 2;
bundle_id = malloc(l);
if (bundle_id == 0)
novm("bundle identifier");
p = bundle_id;
p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname);
if (ho->neg_endpoint || bundle_name)
*p++ = '/';
if (ho->neg_endpoint)
p += slprintf(p, bundle_id+l-p, "%s",
epdisc_to_str(&ho->endpoint));
if (bundle_name)
p += slprintf(p, bundle_id+l-p, "/%v", bundle_name);
/* Make the key for the list of links belonging to the bundle */
l = p - bundle_id;
blinks_id = malloc(l + 7);
if (blinks_id == NULL)
novm("bundle links key");
slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7);
/*
* For demand mode, we only need to configure the bundle
* and attach the link.
*/
mtu = MIN(ho->mrru, ao->mru);
if (demand) {
cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf);
netif_set_mtu(0, mtu);
script_setenv("BUNDLE", bundle_id + 7, 1);
return 0;
}
/*
* Check if the bundle ID is already in the database.
*/
unit = -1;
lock_db();
key.dptr = bundle_id;
key.dsize = p - bundle_id;
pid = tdb_fetch(pppdb, key);
if (pid.dptr != NULL) {
/* bundle ID exists, see if the pppd record exists */
rec = tdb_fetch(pppdb, pid);
if (rec.dptr != NULL && rec.dsize > 0) {
/* make sure the string is null-terminated */
rec.dptr[rec.dsize-1] = 0;
/* parse the interface number */
parse_num(rec.dptr, "IFNAME=ppp", &unit);
/* check the pid value */
if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid)
|| !process_exists(pppd_pid)
|| !owns_unit(pid, unit))
unit = -1;
free(rec.dptr);
}
free(pid.dptr);
}
if (unit >= 0) {
/* attach to existing unit */
if (bundle_attach(unit)) {
set_ifunit(0);
script_setenv("BUNDLE", bundle_id + 7, 0);
make_bundle_links(1);
unlock_db();
info("Link attached to %s", ifname);
return 1;
}
/* attach failed because bundle doesn't exist */
}
/* we have to make a new bundle */
make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf);
set_ifunit(1);
netif_set_mtu(0, mtu);
script_setenv("BUNDLE", bundle_id + 7, 1);
make_bundle_links(0);
unlock_db();
info("New bundle %s created", ifname);
multilink_master = 1;
return 0;
}
void mp_exit_bundle()
{
lock_db();
remove_bundle_link();
unlock_db();
}
static void sendhup(char *str)
{
int pid;
if (parse_num(str, "PPPD_PID=", &pid) && pid != getpid()) {
if (debug)
dbglog("sending SIGHUP to process %d", pid);
kill(pid, SIGHUP);
}
}
void mp_bundle_terminated()
{
TDB_DATA key;
bundle_terminating = 1;
upper_layers_down(0);
notice("Connection terminated.");
print_link_stats();
if (!demand) {
remove_pidfiles();
script_unsetenv("IFNAME");
}
lock_db();
destroy_bundle();
iterate_bundle_links(sendhup);
key.dptr = blinks_id;
key.dsize = strlen(blinks_id);
tdb_delete(pppdb, key);
unlock_db();
new_phase(PHASE_DEAD);
doing_multilink = 0;
multilink_master = 0;
}
static void make_bundle_links(int append)
{
TDB_DATA key, rec;
char *p;
char entry[32];
int l;
key.dptr = blinks_id;
key.dsize = strlen(blinks_id);
slprintf(entry, sizeof(entry), "%s;", db_key);
p = entry;
if (append) {
rec = tdb_fetch(pppdb, key);
if (rec.dptr != NULL && rec.dsize > 0) {
rec.dptr[rec.dsize-1] = 0;
if (strstr(rec.dptr, db_key) != NULL) {
/* already in there? strange */
warn("link entry already exists in tdb");
return;
}
l = rec.dsize + strlen(entry);
p = malloc(l);
if (p == NULL)
novm("bundle link list");
slprintf(p, l, "%s%s", rec.dptr, entry);
} else {
warn("bundle link list not found");
}
if (rec.dptr != NULL)
free(rec.dptr);
}
rec.dptr = p;
rec.dsize = strlen(p) + 1;
if (tdb_store(pppdb, key, rec, TDB_REPLACE))
error("couldn't %s bundle link list",
append? "update": "create");
if (p != entry)
free(p);
}
static void remove_bundle_link()
{
TDB_DATA key, rec;
char entry[32];
char *p, *q;
int l;
key.dptr = blinks_id;
key.dsize = strlen(blinks_id);
slprintf(entry, sizeof(entry), "%s;", db_key);
rec = tdb_fetch(pppdb, key);
if (rec.dptr == NULL || rec.dsize <= 0) {
if (rec.dptr != NULL)
free(rec.dptr);
return;
}
rec.dptr[rec.dsize-1] = 0;
p = strstr(rec.dptr, entry);
if (p != NULL) {
q = p + strlen(entry);
l = strlen(q) + 1;
memmove(p, q, l);
rec.dsize = p - rec.dptr + l;
if (tdb_store(pppdb, key, rec, TDB_REPLACE))
error("couldn't update bundle link list (removal)");
}
free(rec.dptr);
}
static void iterate_bundle_links(void (*func)(char *))
{
TDB_DATA key, rec, pp;
char *p, *q;
key.dptr = blinks_id;
key.dsize = strlen(blinks_id);
rec = tdb_fetch(pppdb, key);
if (rec.dptr == NULL || rec.dsize <= 0) {
error("bundle link list not found (iterating list)");
if (rec.dptr != NULL)
free(rec.dptr);
return;
}
p = rec.dptr;
p[rec.dsize-1] = 0;
while ((q = strchr(p, ';')) != NULL) {
*q = 0;
key.dptr = p;
key.dsize = q - p;
pp = tdb_fetch(pppdb, key);
if (pp.dptr != NULL && pp.dsize > 0) {
pp.dptr[pp.dsize-1] = 0;
func(pp.dptr);
}
if (pp.dptr != NULL)
free(pp.dptr);
p = q + 1;
}
free(rec.dptr);
}
static int
parse_num(str, key, valp)
char *str;
const char *key;
int *valp;
{
char *p, *endp;
int i;
p = strstr(str, key);
if (p != 0) {
p += strlen(key);
i = strtol(p, &endp, 10);
if (endp != p && (*endp == 0 || *endp == ';')) {
*valp = i;
return 1;
}
}
return 0;
}
/*
* Check whether the pppd identified by `key' still owns ppp unit `unit'.
*/
static int
owns_unit(key, unit)
TDB_DATA key;
int unit;
{
char ifkey[32];
TDB_DATA kd, vd;
int ret = 0;
slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit);
kd.dptr = ifkey;
kd.dsize = strlen(ifkey);
vd = tdb_fetch(pppdb, kd);
if (vd.dptr != NULL) {
ret = vd.dsize == key.dsize
&& memcmp(vd.dptr, key.dptr, vd.dsize) == 0;
free(vd.dptr);
}
return ret;
}
static int
get_default_epdisc(ep)
struct epdisc *ep;
{
char *p;
struct hostent *hp;
u_int32_t addr;
/* First try for an ethernet MAC address */
p = get_first_ethernet();
if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) {
ep->class = EPD_MAC;
ep->length = 6;
return 1;
}
/* see if our hostname corresponds to a reasonable IP address */
hp = gethostbyname(hostname);
if (hp != NULL) {
addr = *(u_int32_t *)hp->h_addr;
if (!bad_ip_adrs(addr)) {
addr = ntohl(addr);
if (!LOCAL_IP_ADDR(addr)) {
ep->class = EPD_IP;
set_ip_epdisc(ep, addr);
return 1;
}
}
}
return 0;
}
/*
* epdisc_to_str - make a printable string from an endpoint discriminator.
*/
static char *endp_class_names[] = {
"null", "local", "IP", "MAC", "magic", "phone"
};
char *
epdisc_to_str(ep)
struct epdisc *ep;
{
static char str[MAX_ENDP_LEN*3+8];
u_char *p = ep->value;
int i, mask = 0;
char *q, c, c2;
if (ep->class == EPD_NULL && ep->length == 0)
return "null";
if (ep->class == EPD_IP && ep->length == 4) {
u_int32_t addr;
GETLONG(addr, p);
slprintf(str, sizeof(str), "IP:%I", htonl(addr));
return str;
}
c = ':';
c2 = '.';
if (ep->class == EPD_MAC && ep->length == 6)
c2 = ':';
else if (ep->class == EPD_MAGIC && (ep->length % 4) == 0)
mask = 3;
q = str;
if (ep->class <= EPD_PHONENUM)
q += slprintf(q, sizeof(str)-1, "%s",
endp_class_names[ep->class]);
else
q += slprintf(q, sizeof(str)-1, "%d", ep->class);
c = ':';
for (i = 0; i < ep->length && i < MAX_ENDP_LEN; ++i) {
if ((i & mask) == 0) {
*q++ = c;
c = c2;
}
q += slprintf(q, str + sizeof(str) - q, "%.2x", ep->value[i]);
}
return str;
}
static int hexc_val(int c)
{
if (c >= 'a')
return c - 'a' + 10;
if (c >= 'A')
return c - 'A' + 10;
return c - '0';
}
int
str_to_epdisc(ep, str)
struct epdisc *ep;
char *str;
{
int i, l;
char *p, *endp;
for (i = EPD_NULL; i <= EPD_PHONENUM; ++i) {
int sl = strlen(endp_class_names[i]);
if (strncasecmp(str, endp_class_names[i], sl) == 0) {
str += sl;
break;
}
}
if (i > EPD_PHONENUM) {
/* not a class name, try a decimal class number */
i = strtol(str, &endp, 10);
if (endp == str)
return 0; /* can't parse class number */
str = endp;
}
ep->class = i;
if (*str == 0) {
ep->length = 0;
return 1;
}
if (*str != ':' && *str != '.')
return 0;
++str;
if (i == EPD_IP) {
u_int32_t addr;
i = parse_dotted_ip(str, &addr);
if (i == 0 || str[i] != 0)
return 0;
set_ip_epdisc(ep, addr);
return 1;
}
if (i == EPD_MAC && get_if_hwaddr(ep->value, str) >= 0) {
ep->length = 6;
return 1;
}
p = str;
for (l = 0; l < MAX_ENDP_LEN; ++l) {
if (*str == 0)
break;
if (p <= str)
for (p = str; isxdigit(*p); ++p)
;
i = p - str;
if (i == 0)
return 0;
ep->value[l] = hexc_val(*str++);
if ((i & 1) == 0)
ep->value[l] = (ep->value[l] << 4) + hexc_val(*str++);
if (*str == ':' || *str == '.')
++str;
}
if (*str != 0 || (ep->class == EPD_MAC && l != 6))
return 0;
ep->length = l;
return 1;
}

1797
pppd/options.c Normal file

File diff suppressed because it is too large Load Diff

2
pppd/patchlevel.h Normal file
View File

@ -0,0 +1,2 @@
#define VERSION "2.4.7"
#define DATE "9 August 2014"

65
pppd/pathnames.h Normal file
View File

@ -0,0 +1,65 @@
/*
* define path names
*
* $Id: pathnames.h,v 1.18 2005/08/25 23:59:34 paulus Exp $
*/
#ifdef HAVE_PATHS_H
#include <paths.h>
#else /* HAVE_PATHS_H */
#ifndef _PATH_VARRUN
#define _PATH_VARRUN "/etc/ppp/"
#endif
#define _PATH_DEVNULL "/dev/null"
#endif /* HAVE_PATHS_H */
#ifndef _ROOT_PATH
#define _ROOT_PATH
#endif
#define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets"
#define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets"
#define _PATH_SRPFILE _ROOT_PATH "/etc/ppp/srp-secrets"
#define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options"
#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up"
#define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down"
#define _PATH_IPPREUP _ROOT_PATH "/etc/ppp/ip-pre-up"
#define _PATH_AUTHUP _ROOT_PATH "/etc/ppp/auth-up"
#define _PATH_AUTHDOWN _ROOT_PATH "/etc/ppp/auth-down"
#define _PATH_TTYOPT _ROOT_PATH "/etc/ppp/options."
#define _PATH_CONNERRS _ROOT_PATH "/etc/ppp/connect-errors"
#define _PATH_PEERFILES _ROOT_PATH "/etc/ppp/peers/"
#define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf"
#define _PATH_USEROPT ".ppprc"
#define _PATH_PSEUDONYM ".ppp_pseudonym"
#ifdef INET6
#define _PATH_IPV6UP _ROOT_PATH "/etc/ppp/ipv6-up"
#define _PATH_IPV6DOWN _ROOT_PATH "/etc/ppp/ipv6-down"
#endif
#ifdef IPX_CHANGE
#define _PATH_IPXUP _ROOT_PATH "/etc/ppp/ipx-up"
#define _PATH_IPXDOWN _ROOT_PATH "/etc/ppp/ipx-down"
#endif /* IPX_CHANGE */
#ifdef __STDC__
#define _PATH_PPPDB _ROOT_PATH _PATH_VARRUN "pppd2.tdb"
#else /* __STDC__ */
#ifdef HAVE_PATHS_H
#define _PATH_PPPDB "/var/run/pppd2.tdb"
#else
#define _PATH_PPPDB "/etc/ppp/pppd2.tdb"
#endif
#endif /* __STDC__ */
#ifdef PLUGIN
#ifdef __STDC__
#define _PATH_PLUGIN DESTDIR "/lib/pppd/" VERSION
#else /* __STDC__ */
#define _PATH_PLUGIN "/usr/lib/pppd"
#endif /* __STDC__ */
#endif /* PLUGIN */

View File

@ -0,0 +1,48 @@
#CC = gcc
COPTS = -O2 -g
CFLAGS = $(COPTS) -I.. -I../../include -fPIC
LDFLAGS = -shared
INSTALL = install
DESTDIR = $(INSTROOT)@DESTDIR@
BINDIR = $(DESTDIR)/sbin
MANDIR = $(DESTDIR)/share/man/man8
LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
SUBDIRS := rp-pppoe pppoatm pppol2tp
# Uncomment the next line to include the radius authentication plugin
SUBDIRS += radius
PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so
# This setting should match the one in ../Makefile.linux
MPPE=y
ifdef MPPE
CFLAGS += -DMPPE=1
endif
# include dependencies if present
ifeq (.depend,$(wildcard .depend))
include .depend
endif
all: $(PLUGINS)
for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d all; done
%.so: %.c
$(CC) -o $@ $(LDFLAGS) $(CFLAGS) $^
VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../patchlevel.h)
install: $(PLUGINS)
$(INSTALL) -d $(LIBDIR)
$(INSTALL) $? $(LIBDIR)
for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d install; done
clean:
rm -f *.o *.so *.a
for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d clean; done
depend:
$(CPP) -M $(CFLAGS) *.c >.depend
for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d depend; done

View File

@ -0,0 +1,27 @@
#
# Makefile for plugins on Solaris 2
#
# $Id: Makefile.sol2,v 1.3 2002/09/07 05:15:25 carlsonj Exp $
#
include ../../Makedefs.com
CFLAGS = -c -O -I.. -I../../include $(COPTS)
LDFLAGS = -G
all: minconn.so
minconn.so: minconn.o
ld -o $@ $(LDFLAGS) -h $@ minconn.o
minconn.o: minconn.c
$(CC) $(CFLAGS) -c $?
passprompt.so: passprompt.o
ld -o $@ $(LDFLAGS) -h $@ passprompt.o
passprompt.o: passprompt.c
$(CC) $(CFLAGS) -c $?
clean:
rm -f *.o *.so

66
pppd/plugins/minconn.c Normal file
View File

@ -0,0 +1,66 @@
/*
* minconn.c - pppd plugin to implement a `minconnect' option.
*
* Copyright (c) 1999 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stddef.h>
#include <time.h>
#include "pppd.h"
char pppd_version[] = VERSION;
static int minconnect = 0;
static option_t my_options[] = {
{ "minconnect", o_int, &minconnect,
"Set minimum connect time before idle timeout applies" },
{ NULL }
};
static int my_get_idle(struct ppp_idle *idle)
{
time_t t;
if (idle == NULL)
return minconnect? minconnect: idle_time_limit;
t = idle->xmit_idle;
if (idle->recv_idle < t)
t = idle->recv_idle;
return idle_time_limit - t;
}
void plugin_init(void)
{
info("plugin_init");
add_options(my_options);
idle_time_hook = my_get_idle;
}

110
pppd/plugins/passprompt.c Normal file
View File

@ -0,0 +1,110 @@
/*
* passprompt.c - pppd plugin to invoke an external PAP password prompter
*
* Copyright 1999 Paul Mackerras, Alan Curry.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <syslog.h>
#include "pppd.h"
char pppd_version[] = VERSION;
static char promptprog[PATH_MAX+1];
static option_t options[] = {
{ "promptprog", o_string, promptprog,
"External PAP password prompting program",
OPT_STATIC, NULL, PATH_MAX },
{ NULL }
};
static int promptpass(char *user, char *passwd)
{
int p[2];
pid_t kid;
int readgood, wstat;
ssize_t red;
if (promptprog[0] == 0 || access(promptprog, X_OK) < 0)
return -1; /* sorry, can't help */
if (!passwd)
return 1;
if (pipe(p)) {
warn("Can't make a pipe for %s", promptprog);
return 0;
}
if ((kid = fork()) == (pid_t) -1) {
warn("Can't fork to run %s", promptprog);
close(p[0]);
close(p[1]);
return 0;
}
if (!kid) {
/* we are the child, exec the program */
char *argv[5], fdstr[32];
sys_close();
closelog();
close(p[0]);
seteuid(getuid());
setegid(getgid());
argv[0] = promptprog;
argv[1] = user;
argv[2] = remote_name;
sprintf(fdstr, "%d", p[1]);
argv[3] = fdstr;
argv[4] = 0;
execv(*argv, argv);
_exit(127);
}
/* we are the parent, read the password from the pipe */
close(p[1]);
readgood = 0;
do {
red = read(p[0], passwd + readgood, MAXSECRETLEN-1 - readgood);
if (red == 0)
break;
if (red < 0) {
if (errno == EINTR)
continue;
error("Can't read secret from %s: %m", promptprog);
readgood = -1;
break;
}
readgood += red;
} while (readgood < MAXSECRETLEN - 1);
close(p[0]);
/* now wait for child to exit */
while (waitpid(kid, &wstat, 0) < 0) {
if (errno != EINTR) {
warn("error waiting for %s: %m", promptprog);
break;
}
}
if (readgood < 0)
return 0;
passwd[readgood] = 0;
if (!WIFEXITED(wstat))
warn("%s terminated abnormally", promptprog);
if (WEXITSTATUS(wstat))
warn("%s exited with code %d", promptprog, WEXITSTATUS(status));
return 1;
}
void plugin_init(void)
{
add_options(options);
pap_passwd_hook = promptpass;
}

82
pppd/plugins/passwordfd.c Normal file
View File

@ -0,0 +1,82 @@
/*
* Author: Arvin Schnell <arvin@suse.de>
*
* This plugin let's you pass the password to the pppd via
* a file descriptor. That's easy and secure - no fiddling
* with pap- and chap-secrets files.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "pppd.h"
char pppd_version[] = VERSION;
static int passwdfd = -1;
static char save_passwd[MAXSECRETLEN];
static option_t options[] = {
{ "passwordfd", o_int, &passwdfd,
"Receive password on this file descriptor" },
{ NULL }
};
static int pwfd_check (void)
{
return 1;
}
static int pwfd_passwd (char *user, char *passwd)
{
int readgood, red;
if (passwdfd == -1)
return -1;
if (passwd == NULL)
return 1;
if (passwdfd == -2) {
strcpy (passwd, save_passwd);
return 1;
}
readgood = 0;
do {
red = read (passwdfd, passwd + readgood, MAXSECRETLEN - 1 - readgood);
if (red == 0)
break;
if (red < 0) {
error ("Can't read secret from fd\n");
readgood = -1;
break;
}
readgood += red;
} while (readgood < MAXSECRETLEN - 1);
close (passwdfd);
if (readgood < 0)
return 0;
passwd[readgood] = 0;
strcpy (save_passwd, passwd);
passwdfd = -2;
return 1;
}
void plugin_init (void)
{
add_options (options);
pap_check_hook = pwfd_check;
pap_passwd_hook = pwfd_passwd;
chap_check_hook = pwfd_check;
chap_passwd_hook = pwfd_passwd;
}

View File

@ -0,0 +1,7 @@
The files ans.c, atm.h, atmres.h, atmsap.h, misc.c, text2atm.c and
text2qos.c are taken from the linux-atm libraries. These are
Copyright 1995-2000 EPFL-LRC/ICA, and are licensed under the GNU Lesser
General Public License.
The file pppoatm.c contains its own copyright notice, and is licensed
under the GPL.

View File

@ -0,0 +1,46 @@
#CC = gcc
COPTS = -O2 -g
CFLAGS = $(COPTS) -I../.. -I../../../include -fPIC
LDFLAGS = -shared
INSTALL = install
#***********************************************************************
DESTDIR = $(INSTROOT)@DESTDIR@
LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION)
VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h)
PLUGIN := pppoatm.so
PLUGIN_OBJS := pppoatm.o
#*******
# Do we have the ATM libraries installed? Set HAVE_LIBATM to use them,
# or leave it unset to build the few routines we actually _use_ into
# the plugin directly.
#
#HAVE_LIBATM=yes
ifdef HAVE_LIBATM
LIBS := -latm
else
CFLAGS += -I.
PLUGIN_OBJS += text2qos.o text2atm.o misc.o ans.o
LIBS := -lresolv
endif
#*********
all: $(PLUGIN)
$(PLUGIN): $(PLUGIN_OBJS)
$(CC) $(CFLAGS) -o $@ -shared $^ $(LIBS)
install: all
$(INSTALL) -d -m 755 $(LIBDIR)
$(INSTALL) -c -m 4550 $(PLUGIN) $(LIBDIR)
clean:
rm -f *.o *.so
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<

Some files were not shown because too many files have changed in this diff Show More