mirror of https://gitee.com/openkylin/ppp.git
Import Upstream version 2.4.7
This commit is contained in:
commit
839cb1192c
|
@ -0,0 +1,7 @@
|
|||
*.orig
|
||||
*~
|
||||
*.o
|
||||
*.so
|
||||
*.a
|
||||
*.cat8
|
||||
Makefile
|
|
@ -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.
|
|
@ -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"
|
|
@ -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 $ ##
|
|
@ -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/
|
||||
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
|
@ -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).
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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).
|
||||
|
|
@ -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
|
|
@ -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---
|
||||
|
|
@ -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
|
||||
!
|
|
@ -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`
|
|
@ -0,0 +1 @@
|
|||
chat
|
|
@ -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 *~
|
|
@ -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
|
|
@ -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.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ -z "$DISPLAY" ]; then
|
||||
exec pppgetpass.vt "$@"
|
||||
else
|
||||
exec pppgetpass.gtk "$@"
|
||||
fi
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
# Secrets for authentication using CHAP
|
||||
# client server secret IP addresses
|
|
@ -0,0 +1 @@
|
|||
lock
|
|
@ -0,0 +1,2 @@
|
|||
# Secrets for authentication using PAP
|
||||
# client server secret IP addresses
|
|
@ -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_ */
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -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];
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
pppd
|
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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");
|
||||
}
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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 */
|
||||
};
|
|
@ -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;
|
File diff suppressed because it is too large
Load Diff
|
@ -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__ */
|
|
@ -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 !!?? */
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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) */
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
File diff suppressed because it is too large
Load Diff
|
@ -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 été 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;
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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));
|
File diff suppressed because it is too large
Load Diff
|
@ -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)***********************************/
|
|
@ -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)***********************************/
|
|
@ -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) ********************************
|
||||
*/
|
|
@ -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__ */
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,2 @@
|
|||
#define VERSION "2.4.7"
|
||||
#define DATE "9 August 2014"
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
|
@ -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
Loading…
Reference in New Issue