This commit was manufactured by cvs2svn to create branch 'MP'.

This commit is contained in:
cvs2svn 1998-01-29 00:44:16 +00:00
commit 1ae349f52c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/MP/; revision=32861
88 changed files with 21537 additions and 0 deletions

320
etc/ppp/ppp.conf.sample Normal file
View File

@ -0,0 +1,320 @@
#################################################################
#
# PPP Sample Configuration File
#
# Originally written by Toshiharu OHNO
#
# $Id: ppp.conf.sample,v 1.27 1997/12/30 23:34:35 brian Exp $
#
#################################################################
# This file is separated into sections. Each section is named with
# a label starting in column 0 and followed directly by a ``:''. The
# section continues until the next section. Blank lines and lines
# beginning with ``#'' are ignored.
#
# Lines beginning with "!include" will ``include'' another file. You
# may want to ``!include ~/.ppp.conf'' for backwards compatibility.
#
# Default setup. Always executed when PPP is invoked.
# This section is *not* loaded by the ``load'' or ``dial'' commands.
#
# This is the best place to specify your modem device, it's DTR rate,
# and any logging specification. Logging specs should be done first
# so that subsequent commands are logged.
#
default:
set log Phase Chat Connect Carrier LCP IPCP CCP tun command
set device /dev/cuaa1
set speed 115200
deny lqr
set dial "ABORT BUSY ABORT NO\\sCARRIER TIMEOUT 5 \"\" AT OK-AT-OK ATE1Q0 OK \\dATDT\\T TIMEOUT 40 CONNECT"
# Client side PPP
#
# Although the PPP protocol is a peer to peer protocol, we normally
# consider the side that makes the connection as the client and the
# side that receives the connection as the server. Authentication
# is required by the server either using a unix-style login proceedure
# or by demanding PAP or CHAP authentication from the client.
#
# An on demand example where we have dynamic IP addresses:
# If the peer assigns us an arbitrary IP (most ISPs do this) and we
# can't predict what their IP will be either, take a wild guess at
# some IPs that you can't currently route to. Ensure that the "delete"
# and "add" lines are also present in the pmdemand section of ppp.linkup
# so that when we connect, things will be put straight.
#
# This will work with static IP numbers too. You can also use this entry
# if you don't want on-demand dialup. The "set ifaddr", "delete" and
# "add" lines are required for on-demand. Note, for dynamic IP numbers,
# whether dialing manually or on demand, there should *always* be an entry
# in ppp.linkup.
#
# The /0 bit in "set ifaddr" says that we insist on 0 bits of the
# specified IP actually being correct, therefore, the other side can assign
# any IP numbers.
#
# The forth arg to "set ifaddr" makes us send "0.0.0.0" as our requested
# IP number, forcing the peer to make the decision.
#
pmdemand:
set phone 1234567
set login "TIMEOUT 5 ogin:--ogin: ppp word: ppp"
set timeout 120
set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
delete ALL
add 0 0 HISADDR
# When we want to use PAP or CHAP instead of using a unix-style login
# proceedure, we do the following. Note, the peer suggests whether we
# should send PAP or CHAP. By default, we send whatever we're asked for.
#
PAPorCHAPpmdemand:
set phone 1234567
set login
set authname MyName
set authkey MyKey
set timeout 120
set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
delete ALL
add 0 0 HISADDR
# On demand dialup example with static IP addresses:
# Here, the local side uses 192.244.185.226 and the remote side
# uses 192.244.176.44.
#
# # ppp -auto ondemand
#
# It is not necessary to have an entry in ppp.linkup when both IP numbers
# are static. Be warned though, the MYADDR: label is executed from
# ppp.linkup if the "ondemand:" and "192.244.176.44" labels are not found.
#
ondemand:
set phone 1234567
set login "TIMEOUT 5 ogin:--ogin: ppp word: ppp"
set timeout 120
set ifaddr 192.244.185.226 192.244.176.44 255.255.255.0
delete ALL
add 0 0 HISADDR
# Example segments
#
# The following lines may be included as part of your configuration
# section and aren't themselves complete. They're provided as examples
# of how to achieve different things.
examples:
# Multi-phone example. Numbers separated by a : are used sequentially.
# Numbers separated by a | are used if the previous dial or login script
# failed. Usually, you will prefer to use only one of | or :, but both
# are allowed.
#
set phone 12345678|12345679:12345670|12345671
#
# When in -auto, -ddial, -direct or -background mode, ppp can accept
# control instructions from the ``pppctl'' program. First, you must
# set up your control socket. It's safest to use a UNIX domain socket,
# and watch the permissions:
#
set server /var/tmp/internet 0177
#
# Although a TCP port may be used if you want to allow control
# connections from other machines:
#
set server 6670
#
# If you don't like ppp's builtin chat, use an external one:
#
set login "\"!chat \\\\-f /etc/ppp/ppp.dev.chat\""
#
# If we have a ``strange'' modem that must be re-initialized when we
# hangup:
#
set hangup "\"\" AT OK-AT-OK ATZ OK"
#
# To adjust logging withouth blasting the setting in default:
#
set log -command +tcp/ip
#
# To see log messages on the screen in interactive mode:
#
set log local LCP IPCP CCP
#
# If you're seeing a lot of magic number problems and failed connections,
# try this (check out the FAQ):
#
set openmode passive
#
# For noisy lines, we may want to reconnect (up to 20 times) after loss
# of carrier:
#
set reconnect 3 20
#
# When playing server for M$ clients, tell them who our name servers are:
#
set ns 10.0.0.1 10.0.0.2
set nbns 10.0.0.1 10.0.0.2
enable msext
#
# If we're using the -alias switch, redirect ftp and http to an internal
# machine:
#
alias port 10.0.0.2:ftp ftp
alias port 10.0.0.2:http http
#
# or don't trust the outside at all
#
alias deny_incoming yes
#
# I trust user brian to run ppp, so this goes in the `default' section:
#
allow user brian
#
# But label `internet' contains passwords that even brian can't have, so
# I empty out the user access list in that section:
#
allow users
#
# I also may wish to set up my ppp login script so that it asks the client
# for the label they wish to use. I may only want user ``dodgy'' to access
# their own label in direct mode:
#
dodgy:
allow user dodgy
allow mode direct
#
# If we don't want ICMP and DNS packets to keep the connection alive:
#
set afilter 0 deny icmp
set afilter 1 deny udp src eq 53
set afilter 2 deny udp dst eq 53
set afilter 3 permit 0/0 0/0
#
# And we don't want ICMPs to cause a dialup:
#
set dfilter 0 deny icmp
set dfilter 1 permit 0/0 0/0
#
# Once the line's up, allow connections for ident (113), telnet (23),
# ftp (20 & 21), DNS (53), my place of work (192.244.191.0/24),
# ICMP (ping) and traceroute (>33433).
#
# Anything else is blocked by default
#
set ifilter 0 permit tcp dst eq 113
set ofilter 0 permit tcp src eq 113
set ifilter 1 permit tcp src eq 23 estab
set ofilter 1 permit tcp dst eq 23
set ifilter 2 permit tcp src eq 21 estab
set ofilter 2 permit tcp dst eq 21
set ifilter 3 permit tcp src eq 20 dst gt 1023
set ofilter 3 permit tcp dst eq 20
set ifilter 4 permit udp src eq 53
set ofilter 4 permit udp dst eq 53
set ifilter 5 permit 192.244.191.0/24 0/0
set ofilter 5 permit 0/0 192.244.191.0/24
set ifilter 6 permit icmp
set ofilter 6 permit icmp
set ifilter 7 permit udp dst gt 33433
set ofilter 7 permit udp dst gt 33433
# Server side PPP
# If you want the remote system to authenticate itself, you insist
# that the peer uses CHAP (or PAP) with the "enable" keyword. Both CHAP and
# PAP are disabled by default (we usually only "enable" on of them if the
# other side is dialing into our server).
# When the peer authenticates itself, we use ppp.secret for verification.
#
# Ppp is launched with:
# # ppp -direct CHAPserver
#
# Note: We can supply a third field in ppp.secret specifying the IP address
# for that user.
#
CHAPserver:
enable chap
enable proxy
set ifaddr 192.244.176.44 292.244.184.31
# If we wish to act as a server, allowing PAP access according to
# accounts in /etc/passwd, we do this:
#
PAPServerwithPASSWD:
enable pap
enable passwdauth
enable proxy
set ifaddr 192.244.176.44 292.244.184.31
# Example to connect using a null-modem cable:
# The important thing here is to allow the lqr packets on both sides.
# Without them enabled, we can't tell if the line's dropped - there
# should always be carrier on a direct connection.
# Here, the server sends lqr's every 10 seconds and quits if three in a
# row fail.
#
# Make sure you don't have "deny lqr" in your default: on the client !
#
direct-client:
set dial ""
set line /dev/cuaa0
set sp 115200
set timeout 900 10 3
set log Phase Chat LQM
set login "TIMEOUT 5 ogin:--ogin: ppp word: ppp HELLO"
set ifaddr 10.0.4.2 10.0.4.1
enable lqr
accept lqr
direct-server:
set timeout 900 10 3
set log Phase LQM
set ifaddr 10.0.4.1 10.0.4.2
enable lqr
accept lqr
# Example for PPP over TCP.
# We assume that inetd on tcpsrv.mynet has been
# configured to run "ppp -direct tcp-server" when it gets a connection on
# port 1234. Read the man page for further details
#
tcp-client:
set device tcpsrv.mynet:1234
set dial
set login
set escape 0xff
set ifaddr 10.0.5.1 10.0.4.1 255.255.255.0
tcp-server:
set escape 0xff
set ifaddr 10.0.4.1 10.0.5.1 255.255.255.0
# If you want to test ppp, do it through a loopback:
#
# Requires a line in /etc/services:
# ppploop 6671/tcp # loopback ppp daemon
#
# and a line in /etc/inetd.conf:
# ppploop stream tcp nowait root /usr/sbin/ppp ppp -direct loop-in
#
loop:
set timeout 0
set log phase chat connect lcp ipcp command
set device localhost:ppploop
set dial
set login
set escape 0xff
set ifaddr 127.0.0.2 127.0.0.3
set openmode passive
set server /var/tmp/loop "" 0177
loop-in:
set timeout 0
set log phase chat connect lcp ipcp command
set escape 0xff
allow mode direct

View File

@ -0,0 +1,26 @@
#########################################################################
#
# Example of ppp.linkdown file
#
# This file is checked when ppp closes a connection.
# ppp searches the labels in this file as follows:
#
# 1) The label that matches the IP number assigned to our side.
#
# 2) The label specified on the command line to ppp.
#
# 3) If no label has been found, use MYADDR if it exists.
#
#
# $Id$
#
#########################################################################
# We don't really need to do much here. If we have notified a DNS
# of our temporary IP number, we may want to ``un-notify'' them.
#
# If you're into sound effects when the link goes down, you can run
# ``auplay'' (assuming NAS is installed and configured).
#
MYADDR:
!bg /usr/X11R6/bin/auplay /etc/ppp/linkdown.au

55
etc/ppp/ppp.linkup.sample Normal file
View File

@ -0,0 +1,55 @@
#########################################################################
#
# Example of ppp.linkup file
#
# This file is checked when ppp establishes a connection.
# ppp searches the labels in this file as follows:
#
# 1) The label that matches the IP number assigned to our side.
#
# 2) The label specified on the command line to ppp.
#
# 3) If no label has been found, use MYADDR if it exists.
#
#
# $Id: ppp.linkup.sample,v 1.12 1997/11/18 18:59:57 brian Exp $
#
#########################################################################
# By default, simply delete any existing default route and add the peer
# as default gateway.
# If you're into sound effects when the link comes up, you can run
# ``auplay'' (assuming NAS is installed and configured).
#
MYADDR:
delete 0
add 0 0 HISADDR
!bg /usr/X11R6/bin/auplay /etc/ppp/linkup.au
# If we've got 192.244.176.32 as our address, then regard peer as a gateway
# to 192.244.176.0 network.
#
192.244.176.32:
add 192.244.176.0 0 HISADDR
# If we are invoked with an argument ``pmdemand'', then
# delete all existing (wrong) routing entries and add the peer IP
# as our default gateway.
# This is vital if you don't already know either sides IP number.
#
# We also want to execute a script on startup. This script can do
# nice things such as kick off "sendmail -q", "popclient my.isp" and
# "slurp -d news". It can be passed MYADDR, HISADDR and INTERFACE
# as arguments too - useful for informing a DNS of your assigned IP.
#
pmdemand:
delete ALL
add 0 0 HISADDR
!bg /etc/ppp/ppp.etherup.pmdemand
# If your minimum call charge is 5 minutes, you may as well stay on
# the line for that amount of time. If we want a 60 second subsequent
# timeout, set your timeout to 300 in ppp.conf and then do this:
#
min5minutes:
!bg sh -c "sleep 240; pppctl -p mypassword 3000 set timeout 60"

23
etc/ppp/ppp.secret.sample Normal file
View File

@ -0,0 +1,23 @@
##################################################
#
# Example of ppp.secret file
#
# This file is used to authenticate incoming connections.
# You must ``enable'' either PAP or CHAP in your ppp.conf file.
# The peer may then use any of the Authname/Authkey pairs listed.
# If an IP address is given, it will be assigned to the peer.
#
# If an entry exists for your local machine (as given by the
# ``hostname -s'' command), the password specified will be
# required for all server socket connections. Refer to the ppp(8)
# and pppctl(8) man pages for further details.
#
# $Id: ppp.secret.sample,v 1.4 1997/02/23 09:21:12 peter Exp $
#
##################################################
# Authname Authkey Peer's IP address
oscar OurSecretKey 192.244.184.34/24
BigBird X4dWg9327 192.244.184.33/32
tama localPasswdForControl

43
usr.sbin/ppp/Makefile Normal file
View File

@ -0,0 +1,43 @@
# $Id: Makefile,v 1.35 1998/01/17 14:21:21 brian Exp $
PROG= ppp
SRCS= arp.c async.c auth.c ccp.c chap.c chat.c command.c deflate.c \
defs.c filter.c fsm.c hdlc.c id.c ip.c ipcp.c iplist.c lcp.c \
log.c lqr.c main.c mbuf.c modem.c os.c pap.c phase.c \
pred.c route.c server.c sig.c slcompress.c systems.c throughput.c \
timer.c tun.c vars.c vjcomp.c
CFLAGS+=-Wall
LDADD+= -lmd -lcrypt -lutil -lz
DPADD+= ${LIBMD} ${LIBCRYPT} ${LIBUTIL} ${LIBZ}
MAN8= ppp.8
BINMODE=4550
BINOWN= root
BINGRP= network
.if defined(RELEASE_CRUNCH)
CFLAGS+=-DRELEASE_CRUNCH
.endif
.if defined(NOALIAS) || defined(RELEASE_CRUNCH)
CFLAGS+=-DNOALIAS
.else
SRCS+= alias_cmd.c loadalias.c
.endif
.if exists(${.CURDIR}/../../secure) && !defined(NOCRYPT) && !defined(NOSECURE) && !defined(RELEASE_CRUNCH)
CFLAGS+=-DHAVE_DES
SRCS+= chap_ms.c
LDADD+= -ldes
DPADD+= ${LIBDES}
.endif
.if defined(RELEASE_CRUNCH)
# We must create these objects because the crunchgen will link them,
# and we don't want any unused symbols to spoil the final link.
SRCS+= alias_cmd.c loadalias.c chap_ms.c
chap_ms.o alias_cmd.o loadalias.o:
>null_$*.c
cc -c -o $@ null_$*.c
.endif
.include <bsd.prog.mk>

352
usr.sbin/ppp/README.alias Normal file
View File

@ -0,0 +1,352 @@
User PPP Packet Aliasing
0. Contents
1. Background
2. Setup
3. New commands in ppp
4. Future Work
5. Authors / Acknowledgments
6. Revision History for Aliasing Code
1. Background
User mode ppp has embedded packet aliasing (IP masquerading) code.
Enabling this, either by the "-alias" command line option or the
"alias enable yes" command in a ppp.conf file, makes the ppp host
automatically alias IP packets forwarded from a local network, making
them appear to come from the ppp host machine. Incoming packets
from the outside world are then appropriately de-aliased.
The process of aliasing involves both the IP address and the TCP or UDP
port numbers. ICMP echo and timestamp packets are aliased by their id
numbers. ICMP error messages can be properly directed by examining the
fragment of the offending packet which is contained in the body of the
message.
This software was specifically meant to support users who have
unregistered, private address IP networks (e.g. 192.168.0.x or 10.0.0.x
addresses). The ppp host can act as a gateway for these networks, and
computers on the local area net will have some degree of Internet access
without the need for a registered IP address. Additionally, there will
be no need for an Internet service provider to maintain routing tables
for the local area network.
A disadvantage of packet aliasing is that machines on the local network,
behind the ppp host, are not visible from the outside world. They can
establish TCP connections and make UDP inquiries (such as domain name
service requests) but the connections seem to come from the ppp host
itself. There is, in effect, a partial firewall. Of course, if this is
what you want, the disadvantage becomes an advantage.
A second disadvantage is that "IP encoding" protocols, which send IP
address or port information within the data stream, are not supported
for the cases where exception code exists. This implementation has
workarounds for FTP and IRC DCC, the most well known of the IP encoding
protocols. This frees users from depending on using the ftp passive
mode and avoiding IRC DCC sends, as is sometimes the case with other
masquerading solutions.
The implementation supports all standard, non-encoding TCP and UDP protocols.
Examples of these protocols are http, gopher and telnet. The standard UDP
mode of RealAudio is not presently supported, but the TCP mode does work
correctly.
The packet aliasing code also handle many ICMP messages. In particular,
ping and traceroute are supported.
2. Packet Aliasing Setup
It is recommended that users first verify correct ppp operation without
packet aliasing enabled. This will confirm that the ppp.conf file is
properly set up and that there are no ppp problems. Then start ppp with
the "-alias" option on the command line. The user should verify that
the ppp host can correctly connect to the Internet in packet aliasing
mode. Finally, check that machines on the private network can access
the Internet.
The masquerading software aliases all packets, whether they come from
the host or another computer on the local area network. Thus, a correctly
operating ppp host indicates that the software should work properly for
other computers on the private network.
If the ppp host can access the Internet, but other computers on the local
network cannot, check that IP forwarding is enabled on the ppp host. Also,
verify that the other computers use this machine as a gateway. Of course,
you should also verify that machines within the local area network
communicate properly. A common error is inconsistent subnet addresses
and masks.
3. New commands in ppp
In order to control aliasing behavior in a simple manner (no need for
recompilation), a new command has been added to iij-ppp: alias. This
is in addition to the -alias command line option. System managers and
more experienced users may prefer to use the iij-ppp command syntax
within the ppp.conf file. The alias command also allows packet aliasing
behavior to be more precisely specified.
The decision to add a command instead of extending 'set' or 'option' was
to make obvious that these options only work when aliasing is enabled.
The syntax for 'alias' is
ppp> alias option [yes|no]
where option is given by one of the following templates.
- alias enable [yes|no] (default no)
Enable packet aliasing functionality. If disabled, no other alias
options will have any effect. You should usually enable aliasing
before routing any packets over the link; good points are in the
initial script or right before adding a route. If you do not always
want aliasing, consider using the -alias option to ppp instead of this
command.
- alias deny_incoming [yes|no] (default yes)
Set to "yes" to disable all incoming connections. This just drops
connections to, for example, ftp, telnet or web servers. The aliasing
mechanism prevents these connections. Technically, this option denies
all incoming TCP and UDP requests, making the aliasing software a
fairly efficient one-way firewall. The default is no, which will
all incoming connections to telnetd, ftpd, etc.
- alias log [yes|no]
Controls logging of alias link creation to "/var/log/alias.log" - this
is usually only useful if debugging a setup, to see if the bug is in
the PPP aliasing. The debugging information is fairly limited, listing
the number of aliasing links open for different prototocols.
- alias same_ports [yes|no] (default yes)
When a connection is being established going through the aliasing
routines, it will normally have its port number changed to allow the
aliasing code to track it. If same_ports is enabled, the alias
software attempts to keep the connection's source port unchanged.
This will allow rsh, RPC and other specialized protocols to work
_most of the time_, at least on the host machine. Please, do not
report this being unstable as a bug - it is a result of the way
aliasing has to work. TCP/IP was intended to have one IP address
per machine.
- alias use_sockets [yes|no] (default yes)
This is a fairly obscure option. For the most part, the packet aliasing
software does not have to allocate system sockets when it chooses an
aliasing port number. Under very specific circumstances, FTP data
connections (which don't know the remote port nubmer, though it is
usually 20) and IRC DCC send (which doesn't know either the address or
the port from which the connection will come), there can potentially be
some interference with an open server socket having the same port number
on the ppp host machine. This possibility for interferience only exists
until the TCP connection has been acknowledged on both sides. The safe
option is yes, though fewer system resources are consumed by specifying
no.
- alias unregistered_only [yes|no] (default no)
Packet aliasing normally remaps all packets coming from the local area
network to the ppp host machine address. Set this option to only map
addresses from the following standard ranges for private, unregistered
addresses:
10.0.0.0 -> 10.255.255.255
172.16.0.0 -> 172.31.255.255
192.168.0.0 -> 192.168.255.255 */
In the instance that there is a subnet of public addresses and another
subnet of private addresses being routed by the ppp host, then only the
packets on the private subnet will be aliased.
- alias port <proto> <local addr>:<port> <alias port>
This command allows incoming traffic to <alias port> on the host
machine to be redirected to a specific machine and port on the
local area network. One example of this would be:
alias port tcp 192.168.0.4:telnet 8066
All traffic to port 8066 fthe ppp host would then be sent to
the telnet port (23) of machine 192.168.0.4. Port numbers
can either be designated numerically or by symbolic names
listed in /etc/services. Similarly, addresses can be either
in dotted quad notation or in /etc/hosts.
- alias addr <local addr> <public addr>
This command allows traffic for a public IP address to be
redirected to a machine on the local network. This function
is known as "static NAT". An address assignment of 0 refers
to the default address of the ppp host. Normally static
NAT is useful if your ISP has allocated a small block of
IP addresses to the user, but it can even be used in the
case of a single, dynamically allocated IP address:
alias addr 10.0.0.8 0
The above command would redirect all incoming traffic to
machine 10.0.0.8.
If several address aliases specifiy the same public addres
as follows
alias addr 192.168.0.2 public_addr
alias addr 192.168.0.3 public_addr
alias addr 192.168.0.4 public_addr
then incoming traffice will be directed to the last
translated local address (192.168.0.4), but outgoing
traffic to the first two addresses will still be aliased
to the specified public address.
4. Future Work
What is called packet aliasing here has been variously called masquerading,
network address translation (NAT) and transparent proxying by others. It
is an extremely useful function to many users, but it is also necessarily
imperfect. The occasional IP-encoding protocols always need workarounds
(hacks). Users who are interested in supporting new IP-encoding protocols
can follow the examples of alias_ftp.c and alias_irc.c.
ICMP error messages are currently handled only in the incoming direction.
A handler needs to be added to correctly alias outgoing error messages.
IRC and FTP exception handling make reasonable, though not strictly correct
assumptions, about how IP encoded messages will appear in the control
stream. Programmers may wish to consider how to make this process more
robust.
The packet aliasing engine (alias.c, alias_db.c, alias_ftp.c, alias_irc.c
and alias_util.c) runs in user space, and is intended to be both portable
and reusable for interfaces other than ppp. To access the basic engine
only requires four simple function calls (initialization, communication of
host address, outgoing aliasing and incoming de-aliasing).
5. Authors / Acknowledgments
Charles Mott (cmott@srv.net) <versions 1.0 - 1.8, 2.0, 2.1>
Eivind Eklund (perhaps@yes.no) <versions 1.8b - 1.9, new ppp commands>
Listed below, in chronological order, are individuals who have provided
valuable comments and/or debugging assistance.
Gary Roberts
Tom Torrance
Reto Burkhalter
Martin Renters
Brian Somers
Paul Traina
Ari Suutari
J. Fortes
Andrzej Bialeki
6. Revision History for Aliasing Code
Version 1.0: August 11, 1996 (cjm)
Version 1.1: August 20, 1996 (cjm)
PPP host accepts incoming connections for ports 0 to 1023.
Version 1.2: September 7, 1996 (cjm)
Fragment handling error in alias_db.c corrected.
Version 1.3: September 15, 1996 (cjm)
- Generalized mechanism for handling incoming connections
(no more 0 to 1023 restriction).
- Increased ICMP support (will handle traceroute now).
- Improved TCP close connection logic.
Version 1.4: September 16, 1996
Can't remember (this version only lasted a day -- cjm).
Version 1.5: September 17, 1996 (cjm)
Corrected error in handling incoming UDP packets
with zero checksum.
Version 1.6: September 18, 1996
Simplified ICMP data storage. Will now handle
tracert from Win95 as well as FreeBSD traceroute.
Verstion 1.7: January 9, 1997 (cjm)
- Reduced malloc() activity for ICMP echo and
timestamp requests.
- Added handling for out-of-order IP fragments.
- Switched to differential checksum computation
for IP headers (TCP, UDP and ICMP checksums
were already differential).
- Accepts FTP data connections from other than
port 20. This allows one ftp connections
from two hosts which are both running packet
aliasing.
Verstion 1.8: January 14, 1997 (cjm)
- Fixed data type error in function StartPoint()
in alias_db.c (this bug did not exist before v1.7)
Version 1.8b: January 16, 1997 (Eivind Eklund <perhaps@yes.no>)
- Upgraded base PPP version to be the sourcecode from
FreeBSD 2.1.6, with additional security patches. This
version should still be possible to run on 2.1.5, though -
I've run it with a 2.1.5 kernel without problems.
(Update done with the permission of cjm)
Version 1.9: February 1, 1997 (Eivind Eklund <perhaps@yes.no>)
- Added support for IRC DCC (ee)
- Changed the aliasing routines to use ANSI style throughout -
minor API changes for integration with other programs than PPP (ee)
- Changed the build process, making all options switchable
from the Makefile (ee)
- Fixed minor security hole in alias_ftp.c for other applications
of the aliasing software. Hole could _not_ manifest in
PPP+pktAlias, but could potentially manifest in other
applications of the aliasing. (ee)
- Connections initiated from packet aliasing host machine will
not have their port number aliased unless it conflicts with
an aliasing port already being used. (There is an option to
disable this for debugging) (cjm)
- Sockets will be allocated in cases where there might be
port interference with the host machine. This can be disabled
in cases where the ppp host will be acting purely as a
masquerading router and not generate any traffic of its own.
(cjm)
Version 2.0: March, 1997 (cjm)
- Incoming packets which are not recognized by the packet
aliasing engine are now completely dropped in ip.c.
- Aliasing links are cleared when a host interface address
changes (due to re-dial and dynamic address allocatioa).
- PacketAliasPermanentLink() API added.
- Option for only aliasing private, unregistered IP addresses
added.
- Substantial rework to the aliasing lookup engine.
Version 2.1: May, 1997 (cjm)
- Continuing rework to the aliasing lookup engine to support
multiple incoming addresses and static NAT.
- Now supports outgoing as well as incoming ICMP error messges/
- PPP commands to support address and port redirection.

22
usr.sbin/ppp/README.devel Normal file
View File

@ -0,0 +1,22 @@
This program was originally written by Toshiharu OHNO <tony-o@iij.ad.jp>,
and was submitted to FreeBSD-2.0.5 by Atsushi Murai <amurai@spec.co.jp>.
The original version was usually referred to as iij-ppp.
Ppp is currently maintained under FreeBSD and OpenBSD by Brian Somers
<brian@Awfulhak.org>. The sources for both operating systems are the
same although the Makefiles vary due to the nature of each system.
If and when it's ported to another OS, things will probably be shuffled
around so that there are several Makefiles, one per architecture.
The latest sources are available in FreeBSD-current and OpenBSD-current.
An archive hacked so that it will build on just about any version of
FreeBSD is frequently generated and made available on
http://www.FreeBSD.org/~brian. Once the first OpenBSD release is made
with ppp, an up-to-date OpenBSD archive will be made available too.
A FAQ is available at http://www.FreeBSD.org/FAQ/userppp.html. It applies
equally to OpenBSD as it does to FreeBSD. The man page is quite extensive,
and there are lots of examples in /etc/ppp/ppp.*.sample. These examples
come with the hacked archive above but must be installed manually.
Ppp is still under development. There is no official TODO list.

195
usr.sbin/ppp/alias_cmd.c Normal file
View File

@ -0,0 +1,195 @@
/*-
* The code in this file was written by Eivind Eklund <perhaps@yes.no>,
* who places it in the public domain without restriction.
*
* $Id: alias_cmd.c,v 1.11 1997/12/24 10:28:37 brian Exp $
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "defs.h"
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
#include "vars.h"
#include "alias_cmd.h"
static int StrToAddr(const char *, struct in_addr *);
static int StrToPort(const char *, u_short *, const char *);
static int StrToAddrAndPort(const char *, struct in_addr *, u_short *, const char *);
int
AliasRedirectPort(struct cmdargs const *arg)
{
if (!(mode & MODE_ALIAS)) {
if (VarTerm)
fprintf(VarTerm, "Alias not enabled\n");
return 1;
} else if (arg->argc == 3) {
char proto_constant;
const char *proto;
u_short local_port;
u_short alias_port;
int error;
struct in_addr local_addr;
struct in_addr null_addr;
struct alias_link *link;
proto = arg->argv[0];
if (strcmp(proto, "tcp") == 0) {
proto_constant = IPPROTO_TCP;
} else if (strcmp(proto, "udp") == 0) {
proto_constant = IPPROTO_UDP;
} else {
if (VarTerm) {
fprintf(VarTerm, "port redirect: protocol must be tcp or udp\n");
fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name,
arg->cmd->syntax);
}
return 1;
}
error = StrToAddrAndPort(arg->argv[1], &local_addr, &local_port, proto);
if (error) {
if (VarTerm) {
fprintf(VarTerm, "port redirect: error reading local addr:port\n");
fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
}
return 1;
}
error = StrToPort(arg->argv[2], &alias_port, proto);
if (error) {
if (VarTerm) {
fprintf(VarTerm, "port redirect: error reading alias port\n");
fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
}
return 1;
}
null_addr.s_addr = 0;
link = VarPacketAliasRedirectPort(local_addr, local_port,
null_addr, 0,
null_addr, alias_port,
proto_constant);
if (link == NULL && VarTerm)
fprintf(VarTerm, "port redirect: error returned by packed"
" aliasing engine (code=%d)\n", error);
} else
return -1;
return 0;
}
int
AliasRedirectAddr(struct cmdargs const *arg)
{
if (!(mode & MODE_ALIAS)) {
if (VarTerm)
fprintf(VarTerm, "alias not enabled\n");
return 1;
} else if (arg->argc == 2) {
int error;
struct in_addr local_addr;
struct in_addr alias_addr;
struct alias_link *link;
error = StrToAddr(arg->argv[0], &local_addr);
if (error) {
if (VarTerm)
fprintf(VarTerm, "address redirect: invalid local address\n");
return 1;
}
error = StrToAddr(arg->argv[1], &alias_addr);
if (error) {
if (VarTerm) {
fprintf(VarTerm, "address redirect: invalid alias address\n");
fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
}
return 1;
}
link = VarPacketAliasRedirectAddr(local_addr, alias_addr);
if (link == NULL && VarTerm) {
fprintf(VarTerm, "address redirect: packet aliasing engine error\n");
fprintf(VarTerm, "Usage: alias %s %s\n", arg->cmd->name, arg->cmd->syntax);
}
} else
return -1;
return 0;
}
static int
StrToAddr(const char *str, struct in_addr *addr)
{
struct hostent *hp;
if (inet_aton(str, addr))
return 0;
hp = gethostbyname(str);
if (!hp) {
LogPrintf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
return -1;
}
*addr = *((struct in_addr *) hp->h_addr);
return 0;
}
static int
StrToPort(const char *str, u_short *port, const char *proto)
{
int iport;
struct servent *sp;
char *end;
iport = strtol(str, &end, 10);
if (end != str) {
*port = htons(iport);
return 0;
}
sp = getservbyname(str, proto);
if (!sp) {
LogPrintf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
str, proto);
return -1;
}
*port = sp->s_port;
return 0;
}
static int
StrToAddrAndPort(const char *str, struct in_addr *addr, u_short *port, const char *proto)
{
char *colon;
int res;
colon = strchr(str, ':');
if (!colon) {
LogPrintf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
return -1;
}
*colon = '\0'; /* Cheat the const-ness ! */
res = StrToAddr(str, addr);
*colon = ':'; /* Cheat the const-ness ! */
if (res != 0)
return -1;
return StrToPort(colon+1, port, proto);
}

9
usr.sbin/ppp/alias_cmd.h Normal file
View File

@ -0,0 +1,9 @@
/*-
* The code in this file was written by Eivind Eklund <perhaps@yes.no>,
* who places it in the public domain without restriction.
*
* $Id: alias_cmd.h,v 1.6 1997/12/21 14:28:24 brian Exp $
*/
extern int AliasRedirectPort(struct cmdargs const *);
extern int AliasRedirectAddr(struct cmdargs const *);

355
usr.sbin/ppp/arp.c Normal file
View File

@ -0,0 +1,355 @@
/*
* sys-bsd.c - System-dependent procedures for setting up
* PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
*
* Copyright (c) 1989 Carnegie Mellon University.
* 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 Carnegie Mellon University. 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.
*
* $Id: arp.c,v 1.26 1998/01/23 22:29:16 brian Exp $
*
*/
/*
* TODO:
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <net/if_types.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <sys/uio.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "id.h"
#include "route.h"
#include "arp.h"
#ifdef DEBUG
/*
* To test the proxy arp stuff, just
*
* cc -o arp-test -DDEBUG arp.c
*
*/
#define LogIsKept(x) 1
#define LogPrintf fprintf
#undef LogDEBUG
#define LogDEBUG stderr
#undef LogERROR
#define LogERROR stderr
#undef LogPHASE
#define LogPHASE stdout
#define ID0socket socket
#define ID0ioctl ioctl
#endif
static int rtm_seq;
static int get_ether_addr(int, struct in_addr, struct sockaddr_dl *);
/*
* SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
* if it exists.
*/
#define SET_SA_FAMILY(addr, family) \
memset((char *) &(addr), '\0', sizeof(addr)); \
addr.sa_family = (family); \
addr.sa_len = sizeof(addr);
#if RTM_VERSION >= 3
/*
* sifproxyarp - Make a proxy ARP entry for the peer.
*/
static struct {
struct rt_msghdr hdr;
struct sockaddr_inarp dst;
struct sockaddr_dl hwa;
char extra[128];
} arpmsg;
static int arpmsg_valid;
int
sifproxyarp(int unit, struct in_addr hisaddr)
{
int routes;
/*
* Get the hardware address of an interface on the same subnet as our local
* address.
*/
memset(&arpmsg, 0, sizeof arpmsg);
if (!get_ether_addr(unit, hisaddr, &arpmsg.hwa)) {
LogPrintf(LogERROR, "Cannot determine ethernet address for proxy ARP\n");
return 0;
}
routes = ID0socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (routes < 0) {
LogPrintf(LogERROR, "sifproxyarp: opening routing socket: %s\n",
strerror(errno));
return 0;
}
arpmsg.hdr.rtm_type = RTM_ADD;
arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
arpmsg.hdr.rtm_version = RTM_VERSION;
arpmsg.hdr.rtm_seq = ++rtm_seq;
arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
arpmsg.hdr.rtm_inits = RTV_EXPIRE;
arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
arpmsg.dst.sin_family = AF_INET;
arpmsg.dst.sin_addr.s_addr = hisaddr.s_addr;
arpmsg.dst.sin_other = SIN_PROXY;
arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
+ arpmsg.hwa.sdl_len;
if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
LogPrintf(LogERROR, "Add proxy arp entry: %s\n", strerror(errno));
close(routes);
return 0;
}
close(routes);
arpmsg_valid = 1;
return 1;
}
/*
* cifproxyarp - Delete the proxy ARP entry for the peer.
*/
int
cifproxyarp(int unit, struct in_addr hisaddr)
{
int routes;
if (!arpmsg_valid)
return 0;
arpmsg_valid = 0;
arpmsg.hdr.rtm_type = RTM_DELETE;
arpmsg.hdr.rtm_seq = ++rtm_seq;
routes = ID0socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (routes < 0) {
LogPrintf(LogERROR, "sifproxyarp: opening routing socket: %s\n",
strerror(errno));
return 0;
}
if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
LogPrintf(LogERROR, "Delete proxy arp entry: %s\n", strerror(errno));
close(routes);
return 0;
}
close(routes);
return 1;
}
#else /* RTM_VERSION */
/*
* sifproxyarp - Make a proxy ARP entry for the peer.
*/
int
sifproxyarp(int unit, struct in_addr hisaddr)
{
struct arpreq arpreq;
struct {
struct sockaddr_dl sdl;
char space[128];
} dls;
memset(&arpreq, '\0', sizeof arpreq);
/*
* Get the hardware address of an interface on the same subnet as our local
* address.
*/
if (!get_ether_addr(unit, hisaddr, &dls.sdl)) {
LogPrintf(LOG_PHASE_BIT, "Cannot determine ethernet address for proxy ARP\n");
return 0;
}
arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
arpreq.arp_ha.sa_family = AF_UNSPEC;
memcpy(arpreq.arp_ha.sa_data, LLADDR(&dls.sdl), dls.sdl.sdl_alen);
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr.s_addr;
arpreq.arp_flags = ATF_PERM | ATF_PUBL;
if (ID0ioctl(unit, SIOCSARP, (caddr_t) & arpreq) < 0) {
LogPrintf(LogERROR, "sifproxyarp: ioctl(SIOCSARP): %s\n", strerror(errno));
return 0;
}
return 1;
}
/*
* cifproxyarp - Delete the proxy ARP entry for the peer.
*/
int
cifproxyarp(int unit, struct in_addr hisaddr)
{
struct arpreq arpreq;
memset(&arpreq, '\0', sizeof arpreq);
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr.s_addr;
if (ID0ioctl(unit, SIOCDARP, (caddr_t) & arpreq) < 0) {
LogPrintf(LogERROR, "cifproxyarp: ioctl(SIOCDARP): %s\n", strerror(errno));
return 0;
}
return 1;
}
#endif /* RTM_VERSION */
/*
* get_ether_addr - get the hardware address of an interface on the
* the same subnet as ipaddr.
*/
static int
get_ether_addr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr)
{
int mib[6], sa_len, skip, b;
size_t needed;
char *buf, *ptr, *end;
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct sockaddr *sa;
struct sockaddr_dl *dl;
struct sockaddr_in *ifa, *mask;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
LogPrintf(LogERROR, "get_ether_addr: sysctl: estimate: %s\n",
strerror(errno));
return 0;
}
if ((buf = malloc(needed)) == NULL)
return 0;
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
free(buf);
return 0;
}
end = buf + needed;
ptr = buf;
while (ptr < end) {
ifm = (struct if_msghdr *)ptr; /* On if_msghdr */
if (ifm->ifm_type != RTM_IFINFO)
break;
dl = (struct sockaddr_dl *)(ifm + 1); /* Single _dl at end */
skip = (ifm->ifm_flags & (IFF_UP | IFF_BROADCAST | IFF_POINTOPOINT |
IFF_NOARP | IFF_LOOPBACK)) != (IFF_UP | IFF_BROADCAST);
ptr += ifm->ifm_msglen; /* First ifa_msghdr */
while (ptr < end) {
ifam = (struct ifa_msghdr *)ptr; /* Next ifa_msghdr (alias) */
if (ifam->ifam_type != RTM_NEWADDR) /* finished ? */
break;
sa = (struct sockaddr *)(ifam+1); /* pile of sa's at end */
ptr += ifam->ifam_msglen;
if (skip || (ifam->ifam_addrs & (RTA_NETMASK|RTA_IFA)) !=
(RTA_NETMASK|RTA_IFA))
continue;
/* Found a candidate. Do the addresses match ? */
if (LogIsKept(LogDEBUG) &&
ptr == (char *)ifm + ifm->ifm_msglen + ifam->ifam_msglen)
LogPrintf(LogDEBUG, "%.*s interface is a candidate for proxy\n",
dl->sdl_nlen, dl->sdl_data);
b = 1;
ifa = mask = NULL;
while (b < (RTA_NETMASK|RTA_IFA) && sa < (struct sockaddr *)ptr) {
switch (b) {
case RTA_IFA:
ifa = (struct sockaddr_in *)sa;
break;
case RTA_NETMASK:
/*
* Careful here ! this sockaddr doesn't have sa_family set to
* AF_INET, and is only 8 bytes big ! I have no idea why !
*/
mask = (struct sockaddr_in *)sa;
break;
}
if (ifam->ifam_addrs & b) {
#define ALN sizeof(ifa->sin_addr.s_addr)
sa_len = sa->sa_len > 0 ? ((sa->sa_len-1)|(ALN-1))+1 : ALN;
sa = (struct sockaddr *)((char *)sa + sa_len);
}
b <<= 1;
}
if (LogIsKept(LogDEBUG)) {
char a[16];
strncpy(a, inet_ntoa(mask->sin_addr), sizeof a - 1);
a[sizeof a - 1] = '\0';
LogPrintf(LogDEBUG, "Check addr %s, mask %s\n",
inet_ntoa(ifa->sin_addr), a);
}
if (ifa->sin_family == AF_INET &&
(ifa->sin_addr.s_addr & mask->sin_addr.s_addr) ==
(ipaddr.s_addr & mask->sin_addr.s_addr)) {
LogPrintf(LogPHASE, "Found interface %.*s for proxy arp\n",
dl->sdl_alen, dl->sdl_data);
memcpy(hwaddr, dl, dl->sdl_len);
free(buf);
return 1;
}
}
}
free(buf);
return 0;
}
#ifdef DEBUG
int
main(int argc, char **argv)
{
struct in_addr ipaddr;
int s, f;
s = socket(AF_INET, SOCK_DGRAM, 0);
for (f = 1; f < argc; f++) {
if (inet_aton(argv[f], &ipaddr))
sifproxyarp(s, ipaddr);
}
close(s);
}
#endif

25
usr.sbin/ppp/arp.h Normal file
View File

@ -0,0 +1,25 @@
/*
* User Process PPP
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: arp.h,v 1.6 1997/10/26 01:02:04 brian Exp $
*
*/
extern int cifproxyarp(int, struct in_addr);
extern int sifproxyarp(int, struct in_addr);

197
usr.sbin/ppp/async.c Normal file
View File

@ -0,0 +1,197 @@
/*
* PPP Async HDLC Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: async.c,v 1.14 1997/11/22 03:37:23 brian Exp $
*
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "hdlc.h"
#include "lcp.h"
#include "lcpproto.h"
#include "modem.h"
#include "loadalias.h"
#include "vars.h"
#include "async.h"
#define HDLCSIZE (MAX_MRU*2+6)
static struct async_state {
int mode;
int length;
u_char hbuff[HDLCSIZE]; /* recv buffer */
u_char xbuff[HDLCSIZE]; /* xmit buffer */
u_long my_accmap;
u_long his_accmap;
} AsyncState;
#define MODE_HUNT 0x01
#define MODE_ESC 0x02
void
AsyncInit()
{
struct async_state *stp = &AsyncState;
stp->mode = MODE_HUNT;
stp->length = 0;
stp->my_accmap = stp->his_accmap = 0xffffffff;
}
void
SetLinkParams(struct lcpstate *lcp)
{
struct async_state *stp = &AsyncState;
stp->my_accmap = lcp->want_accmap;
stp->his_accmap = lcp->his_accmap;
}
/*
* Encode into async HDLC byte code if necessary
*/
static void
HdlcPutByte(u_char **cp, u_char c, int proto)
{
u_char *wp;
wp = *cp;
if ((c < 0x20 && (proto == PROTO_LCP || (AsyncState.his_accmap & (1 << c))))
|| (c == HDLC_ESC) || (c == HDLC_SYN)) {
*wp++ = HDLC_ESC;
c ^= HDLC_XOR;
}
if (EscMap[32] && EscMap[c >> 3] & (1 << (c & 7))) {
*wp++ = HDLC_ESC;
c ^= HDLC_XOR;
}
*wp++ = c;
*cp = wp;
}
void
AsyncOutput(int pri, struct mbuf *bp, int proto)
{
struct async_state *hs = &AsyncState;
u_char *cp, *sp, *ep;
struct mbuf *wp;
int cnt;
if (plength(bp) > HDLCSIZE) {
pfree(bp);
return;
}
cp = hs->xbuff;
ep = cp + HDLCSIZE - 10;
wp = bp;
*cp++ = HDLC_SYN;
while (wp) {
sp = MBUF_CTOP(wp);
for (cnt = wp->cnt; cnt > 0; cnt--) {
HdlcPutByte(&cp, *sp++, proto);
if (cp >= ep) {
pfree(bp);
return;
}
}
wp = wp->next;
}
*cp++ = HDLC_SYN;
cnt = cp - hs->xbuff;
LogDumpBuff(LogASYNC, "WriteModem", hs->xbuff, cnt);
WriteModem(pri, (char *) hs->xbuff, cnt);
ModemAddOutOctets(cnt);
pfree(bp);
}
static struct mbuf *
AsyncDecode(u_char c)
{
struct async_state *hs = &AsyncState;
struct mbuf *bp;
if ((hs->mode & MODE_HUNT) && c != HDLC_SYN)
return NULL;
switch (c) {
case HDLC_SYN:
hs->mode &= ~MODE_HUNT;
if (hs->length) { /* packet is ready. */
bp = mballoc(hs->length, MB_ASYNC);
mbwrite(bp, hs->hbuff, hs->length);
hs->length = 0;
return bp;
}
break;
case HDLC_ESC:
if (!(hs->mode & MODE_ESC)) {
hs->mode |= MODE_ESC;
break;
}
/* Fall into ... */
default:
if (hs->length >= HDLCSIZE) {
/* packet is too large, discard it */
LogPrintf(LogERROR, "Packet too large (%d), discarding.\n", hs->length);
hs->length = 0;
hs->mode = MODE_HUNT;
break;
}
if (hs->mode & MODE_ESC) {
c ^= HDLC_XOR;
hs->mode &= ~MODE_ESC;
}
hs->hbuff[hs->length++] = c;
break;
}
return NULL;
}
void
AsyncInput(u_char *buff, int cnt)
{
struct mbuf *bp;
ModemAddInOctets(cnt);
if (DEV_IS_SYNC) {
bp = mballoc(cnt, MB_ASYNC);
memcpy(MBUF_CTOP(bp), buff, cnt);
bp->cnt = cnt;
HdlcInput(bp);
} else {
while (cnt > 0) {
bp = AsyncDecode(*buff++);
if (bp)
HdlcInput(bp);
cnt--;
}
}
}

32
usr.sbin/ppp/async.h Normal file
View File

@ -0,0 +1,32 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
extern void AsyncInit(void);
extern void SetLinkParams(struct lcpstate *);
extern void AsyncOutput(int, struct mbuf *, int);
extern void AsyncInput(u_char *, int);

212
usr.sbin/ppp/auth.c Normal file
View File

@ -0,0 +1,212 @@
/*
* PPP Secret Key Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: auth.c,v 1.26 1998/01/05 01:35:17 brian Exp $
*
* TODO:
* o Implement check against with registered IP addresses.
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "ipcp.h"
#include "loadalias.h"
#include "vars.h"
#include "auth.h"
#include "chat.h"
#include "systems.h"
void
LocalAuthInit()
{
if (!(mode&MODE_DAEMON))
/* We're allowed in interactive mode */
VarLocalAuth = LOCAL_AUTH;
else if (VarHaveLocalAuthKey)
VarLocalAuth = *VarLocalAuthKey == '\0' ? LOCAL_AUTH : LOCAL_NO_AUTH;
else
switch (LocalAuthValidate(SECRETFILE, VarShortHost, "")) {
case NOT_FOUND:
VarLocalAuth = LOCAL_DENY;
break;
case VALID:
VarLocalAuth = LOCAL_AUTH;
break;
case INVALID:
VarLocalAuth = LOCAL_NO_AUTH;
break;
}
}
LOCAL_AUTH_VALID
LocalAuthValidate(const char *fname, const char *system, const char *key)
{
FILE *fp;
int n;
char *vector[3];
char buff[LINE_LEN];
LOCAL_AUTH_VALID rc;
rc = NOT_FOUND; /* No system entry */
fp = OpenSecret(fname);
if (fp == NULL)
return (rc);
while (fgets(buff, sizeof buff, fp)) {
if (buff[0] == '#')
continue;
buff[strlen(buff) - 1] = 0;
memset(vector, '\0', sizeof vector);
n = MakeArgs(buff, vector, VECSIZE(vector));
if (n < 1)
continue;
if (strcmp(vector[0], system) == 0) {
if ((vector[1] == (char *) NULL && (key == NULL || *key == '\0')) ||
(vector[1] != (char *) NULL && strcmp(vector[1], key) == 0)) {
rc = VALID; /* Valid */
} else {
rc = INVALID; /* Invalid */
}
break;
}
}
CloseSecret(fp);
return (rc);
}
int
AuthValidate(const char *fname, const char *system, const char *key)
{
FILE *fp;
int n;
char *vector[5];
char buff[LINE_LEN];
char passwd[100];
fp = OpenSecret(fname);
if (fp == NULL)
return (0);
while (fgets(buff, sizeof buff, fp)) {
if (buff[0] == '#')
continue;
buff[strlen(buff) - 1] = 0;
memset(vector, '\0', sizeof vector);
n = MakeArgs(buff, vector, VECSIZE(vector));
if (n < 2)
continue;
if (strcmp(vector[0], system) == 0) {
ExpandString(vector[1], passwd, sizeof passwd, 0);
if (strcmp(passwd, key) == 0) {
CloseSecret(fp);
if (n > 2 && !UseHisaddr(vector[2], 1))
return (0);
IpcpInit();
if (n > 3)
SetLabel(vector[3]);
return (1); /* Valid */
}
}
}
CloseSecret(fp);
return (0); /* Invalid */
}
char *
AuthGetSecret(const char *fname, const char *system, int len, int setaddr)
{
FILE *fp;
int n;
char *vector[5];
char buff[LINE_LEN];
static char passwd[100];
fp = OpenSecret(fname);
if (fp == NULL)
return (NULL);
while (fgets(buff, sizeof buff, fp)) {
if (buff[0] == '#')
continue;
buff[strlen(buff) - 1] = 0;
memset(vector, '\0', sizeof vector);
n = MakeArgs(buff, vector, VECSIZE(vector));
if (n < 2)
continue;
if (strlen(vector[0]) == len && strncmp(vector[0], system, len) == 0) {
ExpandString(vector[1], passwd, sizeof passwd, 0);
if (setaddr) {
memset(&DefHisAddress, '\0', sizeof DefHisAddress);
}
if (n > 2 && setaddr)
if (UseHisaddr(vector[2], 1))
IpcpInit();
else
return NULL;
if (n > 3)
SetLabel(vector[3]);
return (passwd);
}
}
CloseSecret(fp);
return (NULL); /* Invalid */
}
static void
AuthTimeout(void *vauthp)
{
struct pppTimer *tp;
struct authinfo *authp = (struct authinfo *)vauthp;
tp = &authp->authtimer;
StopTimer(tp);
if (--authp->retry > 0) {
StartTimer(tp);
(authp->ChallengeFunc) (++authp->id);
}
}
void
StartAuthChallenge(struct authinfo *authp)
{
struct pppTimer *tp;
tp = &authp->authtimer;
StopTimer(tp);
tp->func = AuthTimeout;
tp->load = VarRetryTimeout * SECTICKS;
tp->state = TIMER_STOPPED;
tp->arg = (void *) authp;
StartTimer(tp);
authp->retry = 3;
authp->id = 1;
(authp->ChallengeFunc) (authp->id);
}
void
StopAuthTimer(struct authinfo *authp)
{
StopTimer(&authp->authtimer);
}

41
usr.sbin/ppp/auth.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: auth.h,v 1.9 1997/10/26 01:02:09 brian Exp $
*
* TODO:
*/
typedef enum {
VALID,
INVALID,
NOT_FOUND
} LOCAL_AUTH_VALID;
struct authinfo {
void (*ChallengeFunc) (int);
struct pppTimer authtimer;
int retry;
int id;
};
extern LOCAL_AUTH_VALID LocalAuthValidate(const char *, const char *, const char *);
extern void StopAuthTimer(struct authinfo *);
extern void StartAuthChallenge(struct authinfo *);
extern void LocalAuthInit(void);
extern int AuthValidate(const char *, const char *, const char *);
extern char *AuthGetSecret(const char *, const char *, int, int);

432
usr.sbin/ppp/ccp.c Normal file
View File

@ -0,0 +1,432 @@
/*
* PPP Compression Control Protocol (CCP) Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: ccp.c,v 1.29 1998/01/20 22:47:34 brian Exp $
*
* TODO:
* o Support other compression protocols
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "lcpproto.h"
#include "lcp.h"
#include "ccp.h"
#include "phase.h"
#include "loadalias.h"
#include "vars.h"
#include "pred.h"
#include "deflate.h"
struct ccpstate CcpInfo = { -1, -1, -1, -1 };
static void CcpSendConfigReq(struct fsm *);
static void CcpSendTerminateReq(struct fsm *);
static void CcpSendTerminateAck(struct fsm *);
static void CcpDecodeConfig(u_char *, int, int);
static void CcpLayerStart(struct fsm *);
static void CcpLayerFinish(struct fsm *);
static void CcpLayerUp(struct fsm *);
static void CcpLayerDown(struct fsm *);
static void CcpInitRestartCounter(struct fsm *);
struct fsm CcpFsm = {
"CCP",
PROTO_CCP,
CCP_MAXCODE,
0,
ST_INITIAL,
0, 0, 0,
{0, 0, 0, NULL, NULL, NULL}, /* FSM timer */
{0, 0, 0, NULL, NULL, NULL}, /* Open timer */
{0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */
LogCCP,
CcpLayerUp,
CcpLayerDown,
CcpLayerStart,
CcpLayerFinish,
CcpInitRestartCounter,
CcpSendConfigReq,
CcpSendTerminateReq,
CcpSendTerminateAck,
CcpDecodeConfig,
};
static char const *cftypes[] = {
/* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */
"OUI", /* 0: OUI */
"PRED1", /* 1: Predictor type 1 */
"PRED2", /* 2: Predictor type 2 */
"PUDDLE", /* 3: Puddle Jumber */
"???", "???", "???", "???", "???", "???",
"???", "???", "???", "???", "???", "???",
"HWPPC", /* 16: Hewlett-Packard PPC */
"STAC", /* 17: Stac Electronics LZS (rfc1974) */
"MSPPC", /* 18: Microsoft PPC */
"GAND", /* 19: Gandalf FZA (rfc1993) */
"V42BIS", /* 20: ARG->DATA.42bis compression */
"BSD", /* 21: BSD LZW Compress */
"???",
"LZS-DCP", /* 23: LZS-DCP Compression Protocol (rfc1967) */
"MAGNALINK/DEFLATE", /* 24: Magnalink Variable Resource (rfc1975) */
/* 24: Deflate (according to pppd-2.3.1) */
"DCE", /* 25: Data Circuit-Terminating Equip (rfc1976) */
"DEFLATE", /* 26: Deflate (rfc1979) */
};
#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
static const char *
protoname(int proto)
{
if (proto < 0 || proto > NCFTYPES)
return "none";
return cftypes[proto];
}
/* We support these algorithms, and Req them in the given order */
static const struct ccp_algorithm *algorithm[] = {
&DeflateAlgorithm,
&Pred1Algorithm,
&PppdDeflateAlgorithm
};
static int in_algorithm = -1;
static int out_algorithm = -1;
#define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
int
ReportCcpStatus(struct cmdargs const *arg)
{
if (VarTerm) {
fprintf(VarTerm, "%s [%s]\n", CcpFsm.name, StateNames[CcpFsm.state]);
fprintf(VarTerm, "My protocol = %s, His protocol = %s\n",
protoname(CcpInfo.my_proto), protoname(CcpInfo.his_proto));
fprintf(VarTerm, "Output: %ld --> %ld, Input: %ld --> %ld\n",
CcpInfo.uncompout, CcpInfo.compout,
CcpInfo.compin, CcpInfo.uncompin);
}
return 0;
}
static void
ccpstateInit(void)
{
if (CcpInfo.in_init)
(*algorithm[in_algorithm]->i.Term)();
if (CcpInfo.out_init)
(*algorithm[out_algorithm]->o.Term)();
in_algorithm = -1;
out_algorithm = -1;
memset(&CcpInfo, '\0', sizeof CcpInfo);
CcpInfo.his_proto = CcpInfo.my_proto = -1;
CcpInfo.reset_sent = CcpInfo.last_reset = -1;
}
void
CcpInit()
{
FsmInit(&CcpFsm);
ccpstateInit();
CcpFsm.maxconfig = 10;
}
static void
CcpInitRestartCounter(struct fsm *fp)
{
fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
fp->restart = 5;
}
static void
CcpSendConfigReq(struct fsm *fp)
{
u_char *cp;
int f;
LogPrintf(LogCCP, "CcpSendConfigReq\n");
cp = ReqBuff;
CcpInfo.my_proto = -1;
out_algorithm = -1;
for (f = 0; f < NALGORITHMS; f++)
if (Enabled(algorithm[f]->Conf) && !REJECTED(&CcpInfo, algorithm[f]->id)) {
struct lcp_opt o;
(*algorithm[f]->o.Get)(&o);
cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id],
(*algorithm[f]->Disp)(&o));
CcpInfo.my_proto = o.id;
out_algorithm = f;
}
FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
}
void
CcpSendResetReq(struct fsm *fp)
{
LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid);
CcpInfo.reset_sent = fp->reqid;
CcpInfo.last_reset = -1;
FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
}
static void
CcpSendTerminateReq(struct fsm *fp)
{
/* XXX: No code yet */
}
static void
CcpSendTerminateAck(struct fsm *fp)
{
LogPrintf(LogCCP, "CcpSendTerminateAck\n");
FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
}
void
CcpRecvResetReq(struct fsm *fp)
{
if (out_algorithm >= 0 && out_algorithm < NALGORITHMS)
(*algorithm[out_algorithm]->o.Reset)();
}
static void
CcpLayerStart(struct fsm *fp)
{
LogPrintf(LogCCP, "CcpLayerStart.\n");
}
static void
CcpLayerFinish(struct fsm *fp)
{
LogPrintf(LogCCP, "CcpLayerFinish.\n");
ccpstateInit();
}
static void
CcpLayerDown(struct fsm *fp)
{
LogPrintf(LogCCP, "CcpLayerDown.\n");
ccpstateInit();
}
/*
* Called when CCP has reached the OPEN state
*/
static void
CcpLayerUp(struct fsm *fp)
{
LogPrintf(LogCCP, "CcpLayerUp(%d).\n", fp->state);
LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n",
protoname(CcpInfo.my_proto), CcpInfo.my_proto,
protoname(CcpInfo.his_proto), CcpInfo.his_proto);
if (!CcpInfo.in_init && in_algorithm >= 0 && in_algorithm < NALGORITHMS) {
(*algorithm[in_algorithm]->i.Init)();
CcpInfo.in_init = 1;
}
if (!CcpInfo.out_init && out_algorithm >= 0 && out_algorithm < NALGORITHMS) {
(*algorithm[out_algorithm]->o.Init)();
CcpInfo.out_init = 1;
}
}
void
CcpUp()
{
FsmUp(&CcpFsm);
LogPrintf(LogCCP, "CCP Up event!!\n");
}
void
CcpOpen()
{
int f;
for (f = 0; f < NALGORITHMS; f++)
if (Enabled(algorithm[f]->Conf)) {
CcpFsm.open_mode = 0;
FsmOpen(&CcpFsm);
break;
}
if (f == NALGORITHMS)
for (f = 0; f < NALGORITHMS; f++)
if (Acceptable(algorithm[f]->Conf)) {
CcpFsm.open_mode = OPEN_PASSIVE;
FsmOpen(&CcpFsm);
break;
}
}
static void
CcpDecodeConfig(u_char *cp, int plen, int mode_type)
{
int type, length;
int f;
ackp = AckBuff;
nakp = NakBuff;
rejp = RejBuff;
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
if (type < NCFTYPES)
LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length);
else
LogPrintf(LogCCP, " ???[%d]\n", length);
for (f = NALGORITHMS-1; f > -1; f--)
if (algorithm[f]->id == type)
break;
if (f == -1) {
/* Don't understand that :-( */
if (mode_type == MODE_REQ) {
CcpInfo.my_reject |= (1 << type);
memcpy(rejp, cp, length);
rejp += length;
}
} else {
struct lcp_opt o;
switch (mode_type) {
case MODE_REQ:
if (Acceptable(algorithm[f]->Conf) && in_algorithm == -1) {
memcpy(&o, cp, length);
switch ((*algorithm[f]->i.Set)(&o)) {
case MODE_REJ:
memcpy(rejp, &o, o.len);
rejp += o.len;
break;
case MODE_NAK:
memcpy(nakp, &o, o.len);
nakp += o.len;
break;
case MODE_ACK:
memcpy(ackp, cp, length);
ackp += length;
CcpInfo.his_proto = type;
in_algorithm = f; /* This one'll do ! */
break;
}
} else {
memcpy(rejp, cp, length);
rejp += length;
}
break;
case MODE_NAK:
memcpy(&o, cp, length);
if ((*algorithm[f]->o.Set)(&o) == MODE_ACK)
CcpInfo.my_proto = algorithm[f]->id;
else {
CcpInfo.his_reject |= (1 << type);
CcpInfo.my_proto = -1;
}
break;
case MODE_REJ:
CcpInfo.his_reject |= (1 << type);
CcpInfo.my_proto = -1;
break;
}
}
plen -= length;
cp += length;
}
if (rejp != RejBuff) {
ackp = AckBuff; /* let's not send both ! */
CcpInfo.his_proto = -1;
in_algorithm = -1;
}
}
void
CcpInput(struct mbuf *bp)
{
if (phase == PHASE_NETWORK)
FsmInput(&CcpFsm, bp);
else {
if (phase > PHASE_NETWORK)
LogPrintf(LogCCP, "Error: Unexpected CCP in phase %d\n", phase);
pfree(bp);
}
}
void
CcpResetInput(u_char id)
{
if (CcpInfo.reset_sent != -1) {
if (id != CcpInfo.reset_sent) {
LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n",
id, CcpInfo.reset_sent);
return;
}
/* Whaddaya know - a correct reset ack */
} else if (id == CcpInfo.last_reset)
LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n");
else {
LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id);
return;
}
CcpInfo.last_reset = CcpInfo.reset_sent;
CcpInfo.reset_sent = -1;
if (in_algorithm >= 0 && in_algorithm < NALGORITHMS)
(*algorithm[in_algorithm]->i.Reset)();
}
int
CcpOutput(int pri, u_short proto, struct mbuf *m)
{
if (out_algorithm >= 0 && out_algorithm < NALGORITHMS)
return (*algorithm[out_algorithm]->o.Write)(pri, proto, m);
return 0;
}
struct mbuf *
CompdInput(u_short *proto, struct mbuf *m)
{
if (CcpInfo.reset_sent != -1) {
/* Send another REQ and put the packet in the bit bucket */
LogPrintf(LogCCP, "ReSendResetReq(%d)\n", CcpInfo.reset_sent);
FsmOutput(&CcpFsm, CODE_RESETREQ, CcpInfo.reset_sent, NULL, 0);
pfree(m);
} else if (in_algorithm >= 0 && in_algorithm < NALGORITHMS)
return (*algorithm[in_algorithm]->i.Read)(proto, m);
return NULL;
}
void
CcpDictSetup(u_short proto, struct mbuf *m)
{
if (in_algorithm >= 0 && in_algorithm < NALGORITHMS)
(*algorithm[in_algorithm]->i.DictSetup)(proto, m);
}

92
usr.sbin/ppp/ccp.h Normal file
View File

@ -0,0 +1,92 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: ccp.h,v 1.13 1998/01/10 01:55:09 brian Exp $
*
* TODO:
*/
#define CCP_MAXCODE CODE_RESETACK
#define TY_OUI 0 /* OUI */
#define TY_PRED1 1 /* Predictor type 1 */
#define TY_PRED2 2 /* Predictor type 2 */
#define TY_PUDDLE 3 /* Puddle Jumper */
#define TY_HWPPC 16 /* Hewlett-Packard PPC */
#define TY_STAC 17 /* Stac Electronics LZS */
#define TY_MSPPC 18 /* Microsoft PPC */
#define TY_GAND 19 /* Gandalf FZA */
#define TY_V42BIS 20 /* V.42bis compression */
#define TY_BSD 21 /* BSD LZW Compress */
#define TY_PPPD_DEFLATE 24 /* Deflate (gzip) - (mis) numbered by pppd */
#define TY_DEFLATE 26 /* Deflate (gzip) - rfc 1979 */
struct ccpstate {
int his_proto; /* peer's compression protocol */
int my_proto; /* our compression protocol */
int reset_sent; /* If != -1, ignore compressed 'till ack */
int last_reset; /* We can receive more (dups) w/ this id */
u_int32_t his_reject; /* Request codes rejected by peer */
u_int32_t my_reject; /* Request codes I have rejected */
int out_init; /* Init called for out algorithm */
int in_init; /* Init called for in algorithm */
u_long uncompout, compout;
u_long uncompin, compin;
};
extern struct ccpstate CcpInfo;
struct ccp_algorithm {
int id;
int Conf; /* A Conf value from vars.h */
const char *(*Disp)(struct lcp_opt *);
struct {
void (*Get)(struct lcp_opt *);
int (*Set)(struct lcp_opt *);
int (*Init)(void);
void (*Term)(void);
void (*Reset)(void);
struct mbuf *(*Read)(u_short *, struct mbuf *);
void (*DictSetup)(u_short, struct mbuf *);
} i;
struct {
void (*Get)(struct lcp_opt *);
int (*Set)(struct lcp_opt *);
int (*Init)(void);
void (*Term)(void);
void (*Reset)(void);
int (*Write)(int, u_short, struct mbuf *);
} o;
};
extern struct fsm CcpFsm;
extern void CcpRecvResetReq(struct fsm *);
extern void CcpSendResetReq(struct fsm *);
extern void CcpInput(struct mbuf *);
extern void CcpUp(void);
extern void CcpOpen(void);
extern void CcpInit(void);
extern int ReportCcpStatus(struct cmdargs const *);
extern void CcpResetInput(u_char);
extern int CcpOutput(int, u_short, struct mbuf *);
extern struct mbuf *CompdInput(u_short *, struct mbuf *);
extern void CcpDictSetup(u_short, struct mbuf *);

311
usr.sbin/ppp/chap.c Normal file
View File

@ -0,0 +1,311 @@
/*
* PPP CHAP Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: chap.c,v 1.27 1997/12/07 23:55:25 brian Exp $
*
* TODO:
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <ctype.h>
#ifdef HAVE_DES
#include <md4.h>
#endif
#include <md5.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef __OpenBSD__
#include <util.h>
#else
#include <libutil.h>
#endif
#include <utmp.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "chap.h"
#include "chap_ms.h"
#include "lcpproto.h"
#include "lcp.h"
#include "hdlc.h"
#include "phase.h"
#include "loadalias.h"
#include "vars.h"
#include "auth.h"
static const char *chapcodes[] = {
"???", "CHALLENGE", "RESPONSE", "SUCCESS", "FAILURE"
};
static void
ChapOutput(u_int code, u_int id, const u_char * ptr, int count)
{
int plen;
struct fsmheader lh;
struct mbuf *bp;
plen = sizeof(struct fsmheader) + count;
lh.code = code;
lh.id = id;
lh.length = htons(plen);
bp = mballoc(plen, MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
if (count)
memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
LogDumpBp(LogDEBUG, "ChapOutput", bp);
LogPrintf(LogLCP, "ChapOutput: %s\n", chapcodes[code]);
HdlcOutput(PRI_LINK, PROTO_CHAP, bp);
}
static char challenge_data[80];
static int challenge_len;
static void
SendChapChallenge(int chapid)
{
int len, i;
char *cp;
randinit();
cp = challenge_data;
*cp++ = challenge_len = random() % 32 + 16;
for (i = 0; i < challenge_len; i++)
*cp++ = random() & 0xff;
len = strlen(VarAuthName);
memcpy(cp, VarAuthName, len);
cp += len;
ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data);
}
struct authinfo AuthChapInfo = {
SendChapChallenge,
};
static void
RecvChapTalk(struct fsmheader *chp, struct mbuf *bp)
{
int valsize, len;
int arglen, keylen, namelen;
char *cp, *argp, *ap, *name, *digest;
char *keyp;
MD5_CTX MD5context; /* context for MD5 */
char answer[100];
char cdigest[16];
#ifdef HAVE_DES
int ix;
MD4_CTX MD4context; /* context for MD4 */
#endif
len = ntohs(chp->length);
LogPrintf(LogDEBUG, "RecvChapTalk: length: %d\n", len);
arglen = len - sizeof(struct fsmheader);
cp = (char *) MBUF_CTOP(bp);
valsize = *cp++ & 255;
name = cp + valsize;
namelen = arglen - valsize - 1;
name[namelen] = 0;
LogPrintf(LogLCP, " Valsize = %d, Name = \"%s\"\n", valsize, name);
switch (chp->code) {
case CHAP_CHALLENGE:
keyp = VarAuthKey;
keylen = strlen(VarAuthKey);
name = VarAuthName;
namelen = strlen(VarAuthName);
#ifdef HAVE_DES
if (VarMSChap)
argp = malloc(1 + namelen + MS_CHAP_RESPONSE_LEN);
else
#endif
argp = malloc(1 + valsize + namelen + 16);
if (argp == NULL) {
ChapOutput(CHAP_FAILURE, chp->id, "Out of memory!", 14);
return;
}
#ifdef HAVE_DES
if (VarMSChap) {
digest = argp; /* this is the response */
*digest++ = MS_CHAP_RESPONSE_LEN; /* 49 */
memset(digest, '\0', 24);
digest += 24;
ap = answer; /* this is the challenge */
memcpy(ap, keyp, keylen);
ap += 2 * keylen;
memcpy(ap, cp, valsize);
LogDumpBuff(LogDEBUG, "recv", ap, valsize);
ap += valsize;
for (ix = keylen; ix > 0 ; ix--) {
answer[2*ix-2] = answer[ix-1];
answer[2*ix-1] = 0;
}
MD4Init(&MD4context);
MD4Update(&MD4context, answer, 2 * keylen);
MD4Final(digest, &MD4context);
memcpy(digest + 25, name, namelen);
ap += 2 * keylen;
ChapMS(digest, answer + 2 * keylen, valsize);
LogDumpBuff(LogDEBUG, "answer", digest, 24);
ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + MS_CHAP_RESPONSE_LEN + 1);
} else {
#endif
digest = argp;
*digest++ = 16; /* value size */
ap = answer;
*ap++ = chp->id;
memcpy(ap, keyp, keylen);
ap += keylen;
memcpy(ap, cp, valsize);
LogDumpBuff(LogDEBUG, "recv", ap, valsize);
ap += valsize;
MD5Init(&MD5context);
MD5Update(&MD5context, answer, ap - answer);
MD5Final(digest, &MD5context);
LogDumpBuff(LogDEBUG, "answer", digest, 16);
memcpy(digest + 16, name, namelen);
ap += namelen;
/* Send answer to the peer */
ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17);
#ifdef HAVE_DES
}
#endif
free(argp);
break;
case CHAP_RESPONSE:
/*
* Get a secret key corresponds to the peer
*/
keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE);
if (keyp) {
/*
* Compute correct digest value
*/
keylen = strlen(keyp);
ap = answer;
*ap++ = chp->id;
memcpy(ap, keyp, keylen);
ap += keylen;
MD5Init(&MD5context);
MD5Update(&MD5context, answer, ap - answer);
MD5Update(&MD5context, challenge_data + 1, challenge_len);
MD5Final(cdigest, &MD5context);
LogDumpBuff(LogDEBUG, "got", cp, 16);
LogDumpBuff(LogDEBUG, "expect", cdigest, 16);
/*
* Compare with the response
*/
if (memcmp(cp, cdigest, 16) == 0) {
ChapOutput(CHAP_SUCCESS, chp->id, "Welcome!!", 10);
if ((mode & MODE_DIRECT) && isatty(modem) && Enabled(ConfUtmp))
if (Utmp)
LogPrintf(LogERROR, "Oops, already logged in on %s\n",
VarBaseDevice);
else {
struct utmp ut;
memset(&ut, 0, sizeof ut);
time(&ut.ut_time);
strncpy(ut.ut_name, name, sizeof ut.ut_name - 1);
strncpy(ut.ut_line, VarBaseDevice, sizeof ut.ut_line - 1);
if (logout(ut.ut_line))
logwtmp(ut.ut_line, "", "");
login(&ut);
Utmp = 1;
}
NewPhase(PHASE_NETWORK);
break;
}
}
/*
* Peer is not registerd, or response digest is wrong.
*/
ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9);
reconnect(RECON_FALSE);
LcpClose();
break;
}
}
static void
RecvChapResult(struct fsmheader *chp, struct mbuf *bp)
{
int len;
struct lcpstate *lcp = &LcpInfo;
len = ntohs(chp->length);
LogPrintf(LogDEBUG, "RecvChapResult: length: %d\n", len);
if (chp->code == CHAP_SUCCESS) {
if (lcp->auth_iwait == PROTO_CHAP) {
lcp->auth_iwait = 0;
if (lcp->auth_ineed == 0)
NewPhase(PHASE_NETWORK);
}
} else {
/*
* Maybe, we shoud close LCP. Of cause, peer may take close action, too.
*/
;
}
}
void
ChapInput(struct mbuf *bp)
{
int len = plength(bp);
struct fsmheader *chp;
if (len >= sizeof(struct fsmheader)) {
chp = (struct fsmheader *) MBUF_CTOP(bp);
if (len >= ntohs(chp->length)) {
if (chp->code < 1 || chp->code > 4)
chp->code = 0;
LogPrintf(LogLCP, "ChapInput: %s\n", chapcodes[chp->code]);
bp->offset += sizeof(struct fsmheader);
bp->cnt -= sizeof(struct fsmheader);
switch (chp->code) {
case CHAP_RESPONSE:
StopAuthTimer(&AuthChapInfo);
/* Fall into.. */
case CHAP_CHALLENGE:
RecvChapTalk(chp, bp);
break;
case CHAP_SUCCESS:
case CHAP_FAILURE:
RecvChapResult(chp, bp);
break;
}
}
}
pfree(bp);
}

30
usr.sbin/ppp/chap.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: chap.h,v 1.8 1997/10/26 01:02:19 brian Exp $
*
* TODO:
*/
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
#define CHAP_FAILURE 4
extern struct authinfo AuthChapInfo;
extern void ChapInput(struct mbuf *);

112
usr.sbin/ppp/chap_ms.c Normal file
View File

@ -0,0 +1,112 @@
/*
* chap_ms.c - Microsoft MS-CHAP compatible implementation.
*
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
* http://www.strataware.com/
*
* 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 Eric Rosenquist. The name of the author 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.
*
* $Id: chap_ms.c,v 1.4 1997/12/24 09:28:53 brian Exp $
*
*/
#include <sys/types.h>
#include <des.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "command.h"
#include "mbuf.h"
#include "chap_ms.h"
/* unused, for documentation only */
/* only NTResp is filled in for FreeBSD */
typedef struct {
u_char LANManResp[24];
u_char NTResp[24];
u_char UseNT; /* If 1, ignore the LANMan response field */
} MS_ChapResponse;
static void DesEncrypt(u_char *, u_char *, u_char *);
static void MakeKey(u_char *, u_char *);
static void /* IN 8 octets IN 16 octets OUT 24 octets */
ChallengeResponse(u_char *challenge, u_char *pwHash, u_char *response)
{
char ZPasswordHash[21];
memset(ZPasswordHash, '\0', sizeof ZPasswordHash);
memcpy(ZPasswordHash, pwHash, 16);
DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
}
static void /* IN 8 octets IN 7 octest OUT 8 octets */
DesEncrypt(u_char *clear, u_char *key, u_char *cipher)
{
des_cblock des_key;
des_key_schedule key_schedule;
MakeKey(key, des_key);
des_set_key(&des_key, key_schedule);
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
}
static u_char Get7Bits(u_char *input, int startBit)
{
register unsigned int word;
word = (unsigned)input[startBit / 8] << 8;
word |= (unsigned)input[startBit / 8 + 1];
word >>= 15 - (startBit % 8 + 7);
return word & 0xFE;
}
/* IN 56 bit DES key missing parity bits
OUT 64 bit DES key with parity bits added */
static void MakeKey(u_char *key, u_char *des_key)
{
des_key[0] = Get7Bits(key, 0);
des_key[1] = Get7Bits(key, 7);
des_key[2] = Get7Bits(key, 14);
des_key[3] = Get7Bits(key, 21);
des_key[4] = Get7Bits(key, 28);
des_key[5] = Get7Bits(key, 35);
des_key[6] = Get7Bits(key, 42);
des_key[7] = Get7Bits(key, 49);
des_set_odd_parity((des_cblock *)des_key);
}
/* passwordHash 16-bytes MD4 hashed password
challenge 8-bytes peer CHAP challenge
since passwordHash is in a 24-byte buffer, response is written in there */
void
ChapMS(char *passwordHash, char *challenge, int challenge_len)
{
u_char response[24];
ChallengeResponse(challenge, passwordHash, response);
memcpy(passwordHash, response, 24);
passwordHash += 24;
*passwordHash = 1;
}

31
usr.sbin/ppp/chap_ms.h Normal file
View File

@ -0,0 +1,31 @@
/*
* chap.h - Cryptographic Handshake Authentication Protocol definitions.
*
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
* http://www.strataware.com/
*
* 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 Eric Rosenquist. The name of the author 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.
*
* $Id: chap_ms.h,v 1.1 1997/09/25 00:58:20 brian Exp $
*/
/* Max # of (Unicode) chars in an NT password */
#define MAX_NT_PASSWORD 256
/* Don't rely on sizeof(MS_ChapResponse) in case of struct padding */
#define MS_CHAP_RESPONSE_LEN 49
extern void ChapMS(char *, char *, int);

678
usr.sbin/ppp/chat.c Normal file
View File

@ -0,0 +1,678 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com).
*
* Chat -- a program for automatic session establishment (i.e. dial
* the phone and log in).
*
* This software is in the public domain.
*
* Please send all bug reports, requests for information, etc. to:
*
* Karl Fox <karl@MorningStar.Com>
* Morning Star Technologies, Inc.
* 1760 Zollinger Road
* Columbus, OH 43221
* (614)451-1883
*
* $Id: chat.c,v 1.43 1997/12/27 07:22:11 brian Exp $
*
* TODO:
* o Support more UUCP compatible control sequences.
* o Dialing shoud not block monitor process.
* o Reading modem by select should be unified into main.c
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "loadalias.h"
#include "vars.h"
#include "chat.h"
#include "modem.h"
#ifndef isblank
#define isblank(c) ((c) == '\t' || (c) == ' ')
#endif
#define IBSIZE LINE_LEN
static int TimeoutSec;
static int abort_next, timeout_next;
static int numaborts;
static char *AbortStrings[50];
static char inbuff[IBSIZE * 2 + 1];
static jmp_buf ChatEnv;
#define MATCH 1
#define NOMATCH 0
#define ABORT -1
static char *
findblank(char *p, int instring)
{
if (instring) {
while (*p) {
if (*p == '\\') {
strcpy(p, p + 1);
if (!*p)
break;
} else if (*p == '"')
return (p);
p++;
}
} else {
while (*p) {
if (isblank(*p))
return (p);
p++;
}
}
return p;
}
int
MakeArgs(char *script, char **pvect, int maxargs)
{
int nargs, nb;
int instring;
nargs = 0;
while (*script) {
nb = strspn(script, " \t");
script += nb;
if (*script) {
if (*script == '"') {
instring = 1;
script++;
if (*script == '\0')
break; /* Shouldn't return here. Need to null
* terminate below */
} else
instring = 0;
if (nargs >= maxargs - 1)
break;
*pvect++ = script;
nargs++;
script = findblank(script, instring);
if (*script)
*script++ = '\0';
}
}
*pvect = NULL;
return nargs;
}
/*
* \c don't add a cr
* \d Sleep a little (delay 2 seconds
* \n Line feed character
* \P Auth Key password
* \p pause 0.25 sec
* \r Carrige return character
* \s Space character
* \T Telephone number(s) (defined via `set phone')
* \t Tab character
* \U Auth User
*/
char *
ExpandString(const char *str, char *result, int reslen, int sendmode)
{
int addcr = 0;
char *phone;
result[--reslen] = '\0';
if (sendmode)
addcr = 1;
while (*str && reslen > 0) {
switch (*str) {
case '\\':
str++;
switch (*str) {
case 'c':
if (sendmode)
addcr = 0;
break;
case 'd': /* Delay 2 seconds */
nointr_sleep(2);
break;
case 'p':
nointr_usleep(250000);
break; /* Pause 0.25 sec */
case 'n':
*result++ = '\n';
reslen--;
break;
case 'r':
*result++ = '\r';
reslen--;
break;
case 's':
*result++ = ' ';
reslen--;
break;
case 't':
*result++ = '\t';
reslen--;
break;
case 'P':
strncpy(result, VarAuthKey, reslen);
reslen -= strlen(result);
result += strlen(result);
break;
case 'T':
if (VarAltPhone == NULL) {
if (VarNextPhone == NULL) {
strncpy(VarPhoneCopy, VarPhoneList, sizeof VarPhoneCopy - 1);
VarPhoneCopy[sizeof VarPhoneCopy - 1] = '\0';
VarNextPhone = VarPhoneCopy;
}
VarAltPhone = strsep(&VarNextPhone, ":");
}
phone = strsep(&VarAltPhone, "|");
strncpy(result, phone, reslen);
reslen -= strlen(result);
result += strlen(result);
if (VarTerm)
fprintf(VarTerm, "Phone: %s\n", phone);
LogPrintf(LogPHASE, "Phone: %s\n", phone);
break;
case 'U':
strncpy(result, VarAuthName, reslen);
reslen -= strlen(result);
result += strlen(result);
break;
default:
reslen--;
*result++ = *str;
break;
}
if (*str)
str++;
break;
case '^':
str++;
if (*str) {
*result++ = *str++ & 0x1f;
reslen--;
}
break;
default:
*result++ = *str++;
reslen--;
break;
}
}
if (--reslen > 0) {
if (addcr)
*result++ = '\r';
}
if (--reslen > 0)
*result++ = '\0';
return (result);
}
#define MAXLOGBUFF LINE_LEN
static char logbuff[MAXLOGBUFF];
static int loglen = 0;
static void
clear_log(void)
{
memset(logbuff, 0, MAXLOGBUFF);
loglen = 0;
}
static void
flush_log(void)
{
if (LogIsKept(LogCONNECT))
LogPrintf(LogCONNECT, "%s\n", logbuff);
else if (LogIsKept(LogCARRIER) && strstr(logbuff, "CARRIER"))
LogPrintf(LogCARRIER, "%s\n", logbuff);
clear_log();
}
static void
connect_log(const char *str, int single_p)
{
int space = MAXLOGBUFF - loglen - 1;
while (space--) {
if (*str == '\n') {
flush_log();
} else {
logbuff[loglen++] = *str;
}
if (single_p || !*++str)
break;
}
if (!space)
flush_log();
}
static void
ExecStr(char *command, char *out, int olen)
{
pid_t pid;
int fids[2];
char *vector[MAXARGS], *startout, *endout;
int stat, nb;
LogPrintf(LogCHAT, "Exec: %s\n", command);
MakeArgs(command, vector, VECSIZE(vector));
if (pipe(fids) < 0) {
LogPrintf(LogCHAT, "Unable to create pipe in ExecStr: %s\n",
strerror(errno));
longjmp(ChatEnv, 2);
}
if ((pid = fork()) == 0) {
TermTimerService();
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGALRM, SIG_DFL);
if (modem == 2) {
int nmodem;
nmodem = dup(modem);
close(modem);
modem = nmodem;
}
close(fids[0]);
dup2(fids[1], 2);
close(fids[1]);
dup2(modem, 0);
dup2(modem, 1);
if ((nb = open("/dev/tty", O_RDWR)) > 3) {
dup2(nb, 3);
close(nb);
}
setuid(geteuid());
execvp(vector[0], vector);
fprintf(stderr, "execvp failed: %s: %s\n", vector[0], strerror(errno));
exit(127);
} else {
char *name = strdup(vector[0]);
close(fids[1]);
endout = out + olen - 1;
startout = out;
while (out < endout) {
nb = read(fids[0], out, 1);
if (nb <= 0)
break;
out++;
}
*out = '\0';
close(fids[0]);
close(fids[1]);
waitpid(pid, &stat, WNOHANG);
if (WIFSIGNALED(stat)) {
LogPrintf(LogWARN, "%s: signal %d\n", name, WTERMSIG(stat));
free(name);
longjmp(ChatEnv, 3);
} else if (WIFEXITED(stat)) {
switch (WEXITSTATUS(stat)) {
case 0:
free(name);
break;
case 127:
LogPrintf(LogWARN, "%s: %s\n", name, startout);
free(name);
longjmp(ChatEnv, 4);
break;
default:
LogPrintf(LogWARN, "%s: exit %d\n", name, WEXITSTATUS(stat));
free(name);
longjmp(ChatEnv, 5);
break;
}
} else {
LogPrintf(LogWARN, "%s: Unexpected exit result\n", name);
free(name);
longjmp(ChatEnv, 6);
}
}
}
static int
WaitforString(const char *estr)
{
struct timeval timeout;
char *s, *str, ch;
char *inp;
fd_set rfds;
int i, nfds, nb;
char buff[IBSIZE];
#ifdef SIGALRM
int omask;
omask = sigblock(sigmask(SIGALRM));
#endif
clear_log();
if (*estr == '!') {
ExpandString(estr + 1, buff, sizeof buff, 0);
ExecStr(buff, buff, sizeof buff);
} else {
ExpandString(estr, buff, sizeof buff, 0);
}
if (LogIsKept(LogCHAT)) {
s = buff + strlen(buff) - 1;
while (s >= buff && *s == '\n')
s--;
if (!strcmp(estr, buff))
LogPrintf(LogCHAT, "Wait for (%d): %.*s\n",
TimeoutSec, s - buff + 1, buff);
else
LogPrintf(LogCHAT, "Wait for (%d): %s --> %.*s\n",
TimeoutSec, estr, s - buff + 1, buff);
}
if (buff[0] == '\0')
return (MATCH);
str = buff;
inp = inbuff;
if (strlen(str) >= IBSIZE) {
str[IBSIZE - 1] = 0;
LogPrintf(LogCHAT, "Truncating String to %d character: %s\n", IBSIZE, str);
}
nfds = modem + 1;
s = str;
for (;;) {
FD_ZERO(&rfds);
FD_SET(modem, &rfds);
/*
* Because it is not clear whether select() modifies timeout value, it is
* better to initialize timeout values everytime.
*/
timeout.tv_sec = TimeoutSec;
timeout.tv_usec = 0;
i = select(nfds, &rfds, NULL, NULL, &timeout);
#ifdef notdef
TimerService();
#endif
if (i < 0) {
#ifdef SIGALRM
if (errno == EINTR)
continue;
sigsetmask(omask);
#endif
LogPrintf(LogERROR, "WaitForString: select(): %s\n", strerror(errno));
*inp = 0;
return (NOMATCH);
} else if (i == 0) { /* Timeout reached! */
*inp = 0;
if (inp != inbuff)
LogPrintf(LogCHAT, "Got: %s\n", inbuff);
LogPrintf(LogCHAT, "Can't get (%d).\n", timeout.tv_sec);
#ifdef SIGALRM
sigsetmask(omask);
#endif
return (NOMATCH);
}
if (FD_ISSET(modem, &rfds)) { /* got something */
if (DEV_IS_SYNC) {
int length;
if ((length = strlen(inbuff)) > IBSIZE) {
/* shuffle down next part */
memcpy(inbuff, &(inbuff[IBSIZE]), IBSIZE + 1);
length = strlen(inbuff);
}
nb = read(modem, &(inbuff[length]), IBSIZE);
inbuff[nb + length] = 0;
connect_log(inbuff, 0);
if (strstr(inbuff, str)) {
#ifdef SIGALRM
sigsetmask(omask);
#endif
flush_log();
return (MATCH);
}
for (i = 0; i < numaborts; i++) {
if (strstr(inbuff, AbortStrings[i])) {
LogPrintf(LogCHAT, "Abort: %s\n", AbortStrings[i]);
#ifdef SIGALRM
sigsetmask(omask);
#endif
flush_log();
return (ABORT);
}
}
} else {
if (read(modem, &ch, 1) < 0) {
LogPrintf(LogERROR, "read error: %s\n", strerror(errno));
*inp = '\0';
return (NOMATCH);
}
connect_log(&ch, 1);
*inp++ = ch;
if (ch == *s) {
s++;
if (*s == '\0') {
#ifdef SIGALRM
sigsetmask(omask);
#endif
*inp = 0;
flush_log();
return (MATCH);
}
} else
s = str;
if (inp == inbuff + IBSIZE) {
memcpy(inbuff, inp - 100, 100);
inp = inbuff + 100;
}
if (s == str) {
for (i = 0; i < numaborts; i++) { /* Look for Abort strings */
int len;
char *s1;
s1 = AbortStrings[i];
len = strlen(s1);
if ((len <= inp - inbuff) && (strncmp(inp - len, s1, len) == 0)) {
LogPrintf(LogCHAT, "Abort: %s\n", s1);
*inp = 0;
#ifdef SIGALRM
sigsetmask(omask);
#endif
flush_log();
return (ABORT);
}
}
}
}
}
}
}
static void
SendString(const char *str)
{
char *cp;
int on;
char buff[LINE_LEN];
if (abort_next) {
abort_next = 0;
ExpandString(str, buff, sizeof buff, 0);
AbortStrings[numaborts++] = strdup(buff);
} else if (timeout_next) {
timeout_next = 0;
TimeoutSec = atoi(str);
if (TimeoutSec <= 0)
TimeoutSec = 30;
} else {
if (*str == '!') {
ExpandString(str + 1, buff + 2, sizeof buff - 2, 0);
ExecStr(buff + 2, buff + 2, sizeof buff - 2);
} else {
ExpandString(str, buff + 2, sizeof buff - 2, 1);
}
if (strstr(str, "\\P")) /* Do not log the password itself. */
LogPrintf(LogCHAT, "Sending: %s", str);
else {
cp = buff + strlen(buff + 2) + 1;
while (cp >= buff + 2 && *cp == '\n')
cp--;
LogPrintf(LogCHAT, "Sending: %.*s\n", cp - buff - 1, buff + 2);
}
cp = buff;
if (DEV_IS_SYNC)
memcpy(buff, "\377\003", 2); /* Prepend HDLC header */
else
cp += 2;
on = strlen(cp);
write(modem, cp, on);
}
}
static int
ExpectString(char *str)
{
char *minus;
int state;
if (strcmp(str, "ABORT") == 0) {
++abort_next;
return (MATCH);
}
if (strcmp(str, "TIMEOUT") == 0) {
++timeout_next;
return (MATCH);
}
LogPrintf(LogCHAT, "Expecting: %s\n", str);
while (*str) {
/*
* Check whether if string contains sub-send-expect.
*/
for (minus = str; *minus; minus++) {
if (*minus == '-') {
if (minus == str || minus[-1] != '\\')
break;
}
}
if (*minus == '-') { /* We have sub-send-expect. */
*minus = '\0'; /* XXX: Cheat with the const string */
state = WaitforString(str);
*minus = '-'; /* XXX: Cheat with the const string */
minus++;
if (state != NOMATCH)
return (state);
/*
* Can't get expect string. Sendout send part.
*/
str = minus;
for (minus = str; *minus; minus++) {
if (*minus == '-') {
if (minus == str || minus[-1] != '\\')
break;
}
}
if (*minus == '-') {
*minus = '\0'; /* XXX: Cheat with the const string */
SendString(str);
*minus = '-'; /* XXX: Cheat with the const string */
str = ++minus;
} else {
SendString(str);
return (MATCH);
}
} else {
/*
* Simple case. Wait for string.
*/
return (WaitforString(str));
}
}
return (MATCH);
}
static void (*oint) (int);
static void
StopDial(int sig)
{
LogPrintf(LogPHASE, "DoChat: Caught signal %d, abort connect\n", sig);
longjmp(ChatEnv, 1);
}
int
DoChat(char *script)
{
char *vector[MAXARGS];
char *const *argv;
int argc, n, state, err;
if (!script || !*script)
return MATCH;
if ((err = setjmp(ChatEnv))) {
signal(SIGINT, oint);
if (err == 1)
/* Caught a SIGINT during chat */
return (-1);
return (NOMATCH);
}
oint = signal(SIGINT, StopDial);
timeout_next = abort_next = 0;
for (n = 0; AbortStrings[n]; n++) {
free(AbortStrings[n]);
AbortStrings[n] = NULL;
}
numaborts = 0;
memset(vector, '\0', sizeof vector);
argc = MakeArgs(script, vector, VECSIZE(vector));
argv = vector;
TimeoutSec = 30;
while (*argv) {
if (strcmp(*argv, "P_ZERO") == 0 ||
strcmp(*argv, "P_ODD") == 0 || strcmp(*argv, "P_EVEN") == 0) {
ChangeParity(*argv++);
continue;
}
state = ExpectString(*argv++);
switch (state) {
case MATCH:
if (*argv)
SendString(*argv++);
break;
case ABORT:
case NOMATCH:
signal(SIGINT, oint);
return (NOMATCH);
}
}
signal(SIGINT, oint);
return (MATCH);
}

29
usr.sbin/ppp/chat.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com).
*
* Chat -- a program for automatic session establishment (i.e. dial
* the phone and log in).
*
* This software is in the public domain.
*
* Please send all bug reports, requests for information, etc. to:
*
* Karl Fox <karl@MorningStar.Com>
* Morning Star Technologies, Inc.
* 1760 Zollinger Road
* Columbus, OH 43221
* (614)451-1883
*
* $Id: chat.h,v 1.8 1997/10/26 01:02:23 brian Exp $
*
*/
#define VECSIZE(v) (sizeof(v) / sizeof(v[0]))
extern char *ExpandString(const char *, char *, int, int);
extern int MakeArgs(char *, char **, int); /* Mangles the first arg ! */
extern int DoChat(char *); /* passes arg to MakeArgs() */

1681
usr.sbin/ppp/command.c Normal file

File diff suppressed because it is too large Load Diff

62
usr.sbin/ppp/command.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: command.h,v 1.11 1997/11/13 14:43:15 brian Exp $
*
* TODO:
*/
struct cmdtab;
struct cmdargs {
struct cmdtab const *cmd;
int argc;
char const *const *argv;
const void *data;
};
struct cmdtab {
const char *name;
const char *alias;
int (*func) (struct cmdargs const *);
u_char lauth;
const char *helpmes;
const char *syntax;
const void *args;
};
#define VAR_AUTHKEY 0
#define VAR_DIAL 1
#define VAR_LOGIN 2
#define VAR_AUTHNAME 3
#define VAR_DEVICE 4
#define VAR_ACCMAP 5
#define VAR_PHONE 6
#define VAR_HANGUP 7
#ifdef HAVE_DES
#define VAR_ENC 8
#endif
extern struct in_addr ifnetmask;
extern int aft_cmd;
extern int SetVariable(struct cmdargs const *);
extern void Prompt(void);
extern int IsInteractive(int);
extern void InterpretCommand(char *, int, int *, char ***);
extern void RunCommand(int, char const *const *, const char *label);
extern void DecodeCommand(char *, int, const char *label);

617
usr.sbin/ppp/deflate.c Normal file
View File

@ -0,0 +1,617 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: deflate.c,v 1.5 1997/12/28 02:17:06 brian Exp $
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "loadalias.h"
#include "vars.h"
#include "hdlc.h"
#include "lcp.h"
#include "ccp.h"
#include "lcpproto.h"
#include "timer.h"
#include "fsm.h"
#include "deflate.h"
/* Our state */
struct deflate_state {
u_short seqno;
int uncomp_rec;
z_stream cx;
};
static int iWindowSize = 15;
static int oWindowSize = 15;
static struct deflate_state InputState, OutputState;
static char garbage[10];
static u_char EMPTY_BLOCK[4] = { 0x00, 0x00, 0xff, 0xff };
#define DEFLATE_CHUNK_LEN 1024 /* Allocate mbufs this size */
static void
DeflateResetOutput(void)
{
OutputState.seqno = 0;
OutputState.uncomp_rec = 0;
deflateReset(&OutputState.cx);
LogPrintf(LogCCP, "Deflate: Output channel reset\n");
}
static int
DeflateOutput(int pri, u_short proto, struct mbuf *mp)
{
u_char *wp, *rp;
int olen, ilen, len, res, flush;
struct mbuf *mo_head, *mo, *mi_head, *mi;
ilen = plength(mp);
LogPrintf(LogDEBUG, "DeflateOutput: Proto %02x (%d bytes)\n", proto, ilen);
LogDumpBp(LogDEBUG, "DeflateOutput: Compress packet:", mp);
/* Stuff the protocol in front of the input */
mi_head = mi = mballoc(2, MB_HDLCOUT);
mi->next = mp;
rp = MBUF_CTOP(mi);
if (proto < 0x100) { /* Compress the protocol */
rp[0] = proto & 0377;
mi->cnt = 1;
} else { /* Don't compress the protocol */
rp[0] = proto >> 8;
rp[1] = proto & 0377;
mi->cnt = 2;
}
/* Allocate the initial output mbuf */
mo_head = mo = mballoc(DEFLATE_CHUNK_LEN, MB_HDLCOUT);
mo->cnt = 2;
wp = MBUF_CTOP(mo);
*wp++ = OutputState.seqno >> 8;
*wp++ = OutputState.seqno & 0377;
LogPrintf(LogDEBUG, "DeflateOutput: Seq %d\n", OutputState.seqno);
OutputState.seqno++;
/* Set up the deflation context */
OutputState.cx.next_out = wp;
OutputState.cx.avail_out = DEFLATE_CHUNK_LEN - 2;
OutputState.cx.next_in = MBUF_CTOP(mi);
OutputState.cx.avail_in = mi->cnt;
flush = Z_NO_FLUSH;
olen = 0;
while (1) {
if ((res = deflate(&OutputState.cx, flush)) != Z_OK) {
if (res == Z_STREAM_END)
break; /* Done */
LogPrintf(LogERROR, "DeflateOutput: deflate returned %d (%s)\n",
res, OutputState.cx.msg ? OutputState.cx.msg : "");
pfree(mo_head);
mbfree(mi_head);
OutputState.seqno--;
return 1; /* packet dropped */
}
if (flush == Z_SYNC_FLUSH && OutputState.cx.avail_out != 0)
break;
if (OutputState.cx.avail_in == 0 && mi->next != NULL) {
mi = mi->next;
OutputState.cx.next_in = MBUF_CTOP(mi);
OutputState.cx.avail_in = mi->cnt;
if (mi->next == NULL)
flush = Z_SYNC_FLUSH;
}
if (OutputState.cx.avail_out == 0) {
mo->next = mballoc(DEFLATE_CHUNK_LEN, MB_HDLCOUT);
olen += (mo->cnt = DEFLATE_CHUNK_LEN);
mo = mo->next;
mo->cnt = 0;
OutputState.cx.next_out = MBUF_CTOP(mo);
OutputState.cx.avail_out = DEFLATE_CHUNK_LEN;
}
}
olen += (mo->cnt = DEFLATE_CHUNK_LEN - OutputState.cx.avail_out);
olen -= 4; /* exclude the trailing EMPTY_BLOCK */
/*
* If the output packet (including seqno and excluding the EMPTY_BLOCK)
* got bigger, send the original - returning 0 to HdlcOutput() will
* continue to send ``mp''.
*/
if (olen >= ilen) {
pfree(mo_head);
mbfree(mi_head);
LogPrintf(LogDEBUG, "DeflateOutput: %d => %d: Uncompressible (0x%04x)\n",
ilen, olen, proto);
CcpInfo.uncompout += ilen;
CcpInfo.compout += ilen; /* We measure this stuff too */
return 0;
}
pfree(mi_head);
/*
* Lose the last four bytes of our output.
* XXX: We should probably assert that these are the same as the
* contents of EMPTY_BLOCK.
*/
for (mo = mo_head, len = mo->cnt; len < olen; mo = mo->next, len += mo->cnt)
;
mo->cnt -= len - olen;
if (mo->next != NULL) {
pfree(mo->next);
mo->next = NULL;
}
CcpInfo.uncompout += ilen;
CcpInfo.compout += olen;
LogPrintf(LogDEBUG, "DeflateOutput: %d => %d bytes, proto 0x%04x\n",
ilen, olen, proto);
HdlcOutput(PRI_NORMAL, PROTO_COMPD, mo_head);
return 1;
}
static void
DeflateResetInput(void)
{
InputState.seqno = 0;
InputState.uncomp_rec = 0;
inflateReset(&InputState.cx);
LogPrintf(LogCCP, "Deflate: Input channel reset\n");
}
static struct mbuf *
DeflateInput(u_short *proto, struct mbuf *mi)
{
struct mbuf *mo, *mo_head, *mi_head;
u_char *wp;
int ilen, olen;
int seq, flush, res, first;
u_char hdr[2];
LogDumpBp(LogDEBUG, "DeflateInput: Decompress packet:", mi);
mi_head = mi = mbread(mi, hdr, 2);
ilen = 2;
/* Check the sequence number. */
seq = (hdr[0] << 8) + hdr[1];
LogPrintf(LogDEBUG, "DeflateInput: Seq %d\n", seq);
if (seq != InputState.seqno) {
if (seq <= InputState.uncomp_rec)
/*
* So the peer's started at zero again - fine ! If we're wrong,
* inflate() will fail. This is better than getting into a loop
* trying to get a ResetReq to a busy sender.
*/
InputState.seqno = seq;
else {
LogPrintf(LogERROR, "DeflateInput: Seq error: Got %d, expected %d\n",
seq, InputState.seqno);
pfree(mi_head);
CcpSendResetReq(&CcpFsm);
return NULL;
}
}
InputState.seqno++;
InputState.uncomp_rec = 0;
/* Allocate an output mbuf */
mo_head = mo = mballoc(DEFLATE_CHUNK_LEN, MB_IPIN);
/* Our proto starts with 0 if it's compressed */
wp = MBUF_CTOP(mo);
wp[0] = '\0';
/*
* We set avail_out to 1 initially so we can look at the first
* byte of the output and decide whether we have a compressed
* proto field.
*/
InputState.cx.next_in = MBUF_CTOP(mi);
InputState.cx.avail_in = mi->cnt;
InputState.cx.next_out = wp + 1;
InputState.cx.avail_out = 1;
ilen += mi->cnt;
flush = mi->next ? Z_NO_FLUSH : Z_SYNC_FLUSH;
first = 1;
olen = 0;
while (1) {
if ((res = inflate(&InputState.cx, flush)) != Z_OK) {
if (res == Z_STREAM_END)
break; /* Done */
LogPrintf(LogERROR, "DeflateInput: inflate returned %d (%s)\n",
res, InputState.cx.msg ? InputState.cx.msg : "");
pfree(mo_head);
pfree(mi);
CcpSendResetReq(&CcpFsm);
return NULL;
}
if (flush == Z_SYNC_FLUSH && InputState.cx.avail_out != 0)
break;
if (InputState.cx.avail_in == 0 && mi && (mi = mbfree(mi)) != NULL) {
/* underflow */
InputState.cx.next_in = MBUF_CTOP(mi);
ilen += (InputState.cx.avail_in = mi->cnt);
if (mi->next == NULL)
flush = Z_SYNC_FLUSH;
}
if (InputState.cx.avail_out == 0)
/* overflow */
if (first) {
if (!(wp[1] & 1)) {
/* 2 byte proto, shuffle it back in output */
wp[0] = wp[1];
InputState.cx.next_out--;
InputState.cx.avail_out = DEFLATE_CHUNK_LEN-1;
} else
InputState.cx.avail_out = DEFLATE_CHUNK_LEN-2;
first = 0;
} else {
olen += (mo->cnt = DEFLATE_CHUNK_LEN);
mo->next = mballoc(DEFLATE_CHUNK_LEN, MB_IPIN);
mo = mo->next;
InputState.cx.next_out = MBUF_CTOP(mo);
InputState.cx.avail_out = DEFLATE_CHUNK_LEN;
}
}
if (mi != NULL)
pfree(mi);
if (first) {
LogPrintf(LogERROR, "DeflateInput: Length error\n");
pfree(mo_head);
CcpSendResetReq(&CcpFsm);
return NULL;
}
olen += (mo->cnt = DEFLATE_CHUNK_LEN - InputState.cx.avail_out);
*proto = ((u_short)wp[0] << 8) | wp[1];
mo_head->offset += 2;
mo_head->cnt -= 2;
olen -= 2;
CcpInfo.compin += ilen;
CcpInfo.uncompin += olen;
LogPrintf(LogDEBUG, "DeflateInput: %d => %d bytes, proto 0x%04x\n",
ilen, olen, *proto);
/*
* Simulate an EMPTY_BLOCK so that our dictionary stays in sync.
* The peer will have silently removed this!
*/
InputState.cx.next_out = garbage;
InputState.cx.avail_out = sizeof garbage;
InputState.cx.next_in = EMPTY_BLOCK;
InputState.cx.avail_in = sizeof EMPTY_BLOCK;
inflate(&InputState.cx, Z_SYNC_FLUSH);
return mo_head;
}
static void
DeflateDictSetup(u_short proto, struct mbuf *mi)
{
int res, flush, expect_error;
u_char *rp;
struct mbuf *mi_head;
short len;
LogPrintf(LogDEBUG, "DeflateDictSetup: Got seq %d\n", InputState.seqno);
/*
* Stuff an ``uncompressed data'' block header followed by the
* protocol in front of the input
*/
mi_head = mballoc(7, MB_HDLCOUT);
mi_head->next = mi;
len = plength(mi);
mi = mi_head;
rp = MBUF_CTOP(mi);
if (proto < 0x100) { /* Compress the protocol */
rp[5] = proto & 0377;
mi->cnt = 6;
len++;
} else { /* Don't compress the protocol */
rp[5] = proto >> 8;
rp[6] = proto & 0377;
mi->cnt = 7;
len += 2;
}
rp[0] = 0x80; /* BITS: 100xxxxx */
rp[1] = len & 0377; /* The length */
rp[2] = len >> 8;
rp[3] = (~len) & 0377; /* One's compliment of the length */
rp[4] = (~len) >> 8;
InputState.cx.next_in = rp;
InputState.cx.avail_in = mi->cnt;
InputState.cx.next_out = garbage;
InputState.cx.avail_out = sizeof garbage;
flush = Z_NO_FLUSH;
expect_error = 0;
while (1) {
if ((res = inflate(&InputState.cx, flush)) != Z_OK) {
if (res == Z_STREAM_END)
break; /* Done */
if (expect_error && res == Z_BUF_ERROR)
break;
LogPrintf(LogERROR, "DeflateDictSetup: inflate returned %d (%s)\n",
res, InputState.cx.msg ? InputState.cx.msg : "");
LogPrintf(LogERROR, "DeflateDictSetup: avail_in %d, avail_out %d\n",
InputState.cx.avail_in, InputState.cx.avail_out);
CcpSendResetReq(&CcpFsm);
mbfree(mi_head); /* lose our allocated ``head'' buf */
return;
}
if (flush == Z_SYNC_FLUSH && InputState.cx.avail_out != 0)
break;
if (InputState.cx.avail_in == 0 && mi && (mi = mi->next) != NULL) {
/* underflow */
InputState.cx.next_in = MBUF_CTOP(mi);
InputState.cx.avail_in = mi->cnt;
if (mi->next == NULL)
flush = Z_SYNC_FLUSH;
}
if (InputState.cx.avail_out == 0) {
if (InputState.cx.avail_in == 0)
/*
* This seems to be a bug in libz ! If inflate() finished
* with 0 avail_in and 0 avail_out *and* this is the end of
* our input *and* inflate() *has* actually written all the
* output it's going to, it *doesn't* return Z_STREAM_END !
* When we subsequently call it with no more input, it gives
* us Z_BUF_ERROR :-( It seems pretty safe to ignore this
* error (the dictionary seems to stay in sync). In the worst
* case, we'll drop the next compressed packet and do a
* CcpReset() then.
*/
expect_error = 1;
/* overflow */
InputState.cx.next_out = garbage;
InputState.cx.avail_out = sizeof garbage;
}
}
CcpInfo.compin += len;
CcpInfo.uncompin += len;
InputState.seqno++;
InputState.uncomp_rec++;
mbfree(mi_head); /* lose our allocated ``head'' buf */
}
static const char *
DeflateDispOpts(struct lcp_opt *o)
{
static char disp[7];
sprintf(disp, "win %d", (o->data[0]>>4) + 8);
return disp;
}
static void
DeflateGetInputOpts(struct lcp_opt *o)
{
o->id = TY_DEFLATE;
o->len = 4;
o->data[0] = ((iWindowSize-8)<<4)+8;
o->data[1] = '\0';
}
static void
DeflateGetOutputOpts(struct lcp_opt *o)
{
o->id = TY_DEFLATE;
o->len = 4;
o->data[0] = ((oWindowSize-8)<<4)+8;
o->data[1] = '\0';
}
static void
PppdDeflateGetInputOpts(struct lcp_opt *o)
{
o->id = TY_PPPD_DEFLATE;
o->len = 4;
o->data[0] = ((iWindowSize-8)<<4)+8;
o->data[1] = '\0';
}
static void
PppdDeflateGetOutputOpts(struct lcp_opt *o)
{
o->id = TY_PPPD_DEFLATE;
o->len = 4;
o->data[0] = ((oWindowSize-8)<<4)+8;
o->data[1] = '\0';
}
static int
DeflateSetOpts(struct lcp_opt *o, int *sz)
{
if (o->len != 4 || (o->data[0]&15) != 8 || o->data[1] != '\0') {
return MODE_REJ;
}
*sz = (o->data[0] >> 4) + 8;
if (*sz > 15) {
*sz = 15;
return MODE_NAK;
}
return MODE_ACK;
}
static int
DeflateSetInputOpts(struct lcp_opt *o)
{
int res;
res = DeflateSetOpts(o, &iWindowSize);
if (res != MODE_ACK)
DeflateGetInputOpts(o);
return res;
}
static int
DeflateSetOutputOpts(struct lcp_opt *o)
{
int res;
res = DeflateSetOpts(o, &oWindowSize);
if (res != MODE_ACK)
DeflateGetOutputOpts(o);
return res;
}
static int
PppdDeflateSetInputOpts(struct lcp_opt *o)
{
int res;
res = DeflateSetOpts(o, &iWindowSize);
if (res != MODE_ACK)
PppdDeflateGetInputOpts(o);
return res;
}
static int
PppdDeflateSetOutputOpts(struct lcp_opt *o)
{
int res;
res = DeflateSetOpts(o, &oWindowSize);
if (res != MODE_ACK)
PppdDeflateGetOutputOpts(o);
return res;
}
static int
DeflateInitInput(void)
{
InputState.cx.zalloc = NULL;
InputState.cx.opaque = NULL;
InputState.cx.zfree = NULL;
InputState.cx.next_out = NULL;
if (inflateInit2(&InputState.cx, -iWindowSize) != Z_OK)
return 0;
DeflateResetInput();
return 1;
}
static int
DeflateInitOutput(void)
{
OutputState.cx.zalloc = NULL;
OutputState.cx.opaque = NULL;
OutputState.cx.zfree = NULL;
OutputState.cx.next_in = NULL;
if (deflateInit2(&OutputState.cx, Z_DEFAULT_COMPRESSION, 8,
-oWindowSize, 8, Z_DEFAULT_STRATEGY) != Z_OK)
return 0;
DeflateResetOutput();
return 1;
}
static void
DeflateTermInput(void)
{
iWindowSize = 15;
inflateEnd(&InputState.cx);
}
static void
DeflateTermOutput(void)
{
oWindowSize = 15;
deflateEnd(&OutputState.cx);
}
const struct ccp_algorithm PppdDeflateAlgorithm = {
TY_PPPD_DEFLATE, /* pppd (wrongly) expects this ``type'' field */
ConfPppdDeflate,
DeflateDispOpts,
{
PppdDeflateGetInputOpts,
PppdDeflateSetInputOpts,
DeflateInitInput,
DeflateTermInput,
DeflateResetInput,
DeflateInput,
DeflateDictSetup
},
{
PppdDeflateGetOutputOpts,
PppdDeflateSetOutputOpts,
DeflateInitOutput,
DeflateTermOutput,
DeflateResetOutput,
DeflateOutput
},
};
const struct ccp_algorithm DeflateAlgorithm = {
TY_DEFLATE, /* rfc 1979 */
ConfDeflate,
DeflateDispOpts,
{
DeflateGetInputOpts,
DeflateSetInputOpts,
DeflateInitInput,
DeflateTermInput,
DeflateResetInput,
DeflateInput,
DeflateDictSetup
},
{
DeflateGetOutputOpts,
DeflateSetOutputOpts,
DeflateInitOutput,
DeflateTermOutput,
DeflateResetOutput,
DeflateOutput
},
};

30
usr.sbin/ppp/deflate.h Normal file
View File

@ -0,0 +1,30 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
extern const struct ccp_algorithm PppdDeflateAlgorithm;
extern const struct ccp_algorithm DeflateAlgorithm;

116
usr.sbin/ppp/defs.c Normal file
View File

@ -0,0 +1,116 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: defs.c,v 1.10 1997/12/30 20:02:50 brian Exp $
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "defs.h"
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
#include "vars.h"
int mode = MODE_INTER;
int BGFiledes[2] = { -1, -1 };
int modem = -1;
int tun_in = -1;
int tun_out = -1;
int netfd = -1;
static char dstsystem[50];
void
SetLabel(const char *label)
{
if (label)
strncpy(dstsystem, label, sizeof dstsystem - 1);
else
*dstsystem = '\0';
}
const char *
GetLabel()
{
return *dstsystem ? dstsystem : NULL;
}
void
randinit()
{
#ifdef __FreeBSD__
static int initdone;
if (!initdone) {
initdone = 1;
srandomdev();
}
#else
srandom(time(NULL)^getpid());
#endif
}
int
GetShortHost()
{
char *p;
if (gethostname(VarShortHost, sizeof VarShortHost)) {
LogPrintf(LogERROR, "GetShortHost: gethostname: %s\n", strerror(errno));
return 0;
}
if ((p = strchr(VarShortHost, '.')))
*p = '\0';
return 1;
}
void
DropClient(int verbose)
{
FILE *oVarTerm;
if (VarTerm && !(mode & MODE_INTER)) {
oVarTerm = VarTerm;
VarTerm = 0;
if (oVarTerm)
fclose(oVarTerm);
close(netfd);
netfd = -1;
if (verbose)
LogPrintf(LogPHASE, "Client connection dropped.\n");
}
}

95
usr.sbin/ppp/defs.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: defs.h,v 1.28 1997/11/22 03:37:29 brian Exp $
*
* TODO:
*/
/*
* Check following definitions for your machine environment
*/
#ifdef __FreeBSD__
# define MODEM_DEV "/dev/cuaa1" /* name of tty device */
# define BASE_MODEM_DEV "cuaa1" /* name of base tty device */
#else
# ifdef __OpenBSD__
# define MODEM_DEV "/dev/cua01" /* name of tty device */
# define BASE_MODEM_DEV "cua01" /* name of base tty device */
# else
# define MODEM_DEV "/dev/tty01" /* name of tty device */
# define BASE_MODEM_DEV "tty01" /* name of base tty device */
# endif
#endif
#define MODEM_SPEED B38400 /* tty speed */
#define SERVER_PORT 3000 /* Base server port no. */
#define MODEM_CTSRTS 1 /* Default (true): use CTS/RTS signals */
#define RECONNECT_TIMER 3 /* Default timer for carrier loss */
#define RECONNECT_TRIES 0 /* Default retries on carrier loss */
#define REDIAL_PERIOD 30 /* Default Hold time to redial */
#define NEXT_REDIAL_PERIOD 3 /* Default Hold time to next number redial */
#define SCRIPT_LEN 512 /* Size of login scripts */
#define LINE_LEN SCRIPT_LEN /* Size of login scripts */
#define MAXARGS 40 /* How many args per config line */
#define CONFFILE "ppp.conf"
#define LINKUPFILE "ppp.linkup"
#define LINKDOWNFILE "ppp.linkdown"
#define SECRETFILE "ppp.secret"
/*
* Definition of working mode
*/
#define MODE_INTER 1 /* Interactive mode */
#define MODE_AUTO 2 /* Auto calling mode */
#define MODE_DIRECT 4 /* Direct connection mode */
#define MODE_DEDICATED 8 /* Dedicated line mode */
#define MODE_DDIAL 16 /* Dedicated dialing line mode */
#define MODE_ALIAS 32 /* Packet aliasing (masquerading) */
#define MODE_BACKGROUND 64 /* Background mode. */
#define MODE_DAEMON (2|4|8|16|64)
#define MODE_OUTGOING_DAEMON (2|8|16|64)
#define EX_SIG -1
#define EX_NORMAL 0
#define EX_START 1
#define EX_SOCK 2
#define EX_MODEM 3
#define EX_DIAL 4
#define EX_DEAD 5
#define EX_DONE 6
#define EX_REBOOT 7
#define EX_ERRDEAD 8
#define EX_HANGUP 10
#define EX_TERM 11
#define EX_NODIAL 12
#define EX_NOLOGIN 13
extern int mode;
extern int BGFiledes[2];
extern int modem;
extern int tun_in;
extern int tun_out;
extern int netfd;
extern void SetLabel(const char *);
extern const char *GetLabel(void);
extern void randinit(void);
extern int GetShortHost(void);
extern void DropClient(int);

499
usr.sbin/ppp/filter.c Normal file
View File

@ -0,0 +1,499 @@
/*
* PPP Filter command Interface
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: filter.c,v 1.21 1997/12/24 09:28:57 brian Exp $
*
* TODO: Shoud send ICMP error message when we discard packets.
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
#include "defs.h"
#include "vars.h"
#include "ipcp.h"
#include "filter.h"
struct filterent ifilters[MAXFILTERS]; /* incoming packet filter */
struct filterent ofilters[MAXFILTERS]; /* outgoing packet filter */
struct filterent dfilters[MAXFILTERS]; /* dial-out packet filter */
struct filterent afilters[MAXFILTERS]; /* keep-alive packet filter */
static struct filterent filterdata;
static u_long netmasks[33] = {
0x00000000,
0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,
0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000,
0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00,
0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0,
0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF,
};
int
ParseAddr(int argc,
char const *const *argv,
struct in_addr * paddr,
struct in_addr * pmask,
int *pwidth)
{
int bits, len;
char *wp;
const char *cp;
if (argc < 1) {
LogPrintf(LogWARN, "ParseAddr: address/mask is expected.\n");
return (0);
}
if (pmask)
pmask->s_addr = 0xffffffff; /* Assume 255.255.255.255 as default */
cp = pmask || pwidth ? strchr(*argv, '/') : NULL;
len = cp ? cp - *argv : strlen(*argv);
if (strncasecmp(*argv, "HISADDR", len) == 0)
*paddr = IpcpInfo.his_ipaddr;
else if (strncasecmp(*argv, "MYADDR", len) == 0)
*paddr = IpcpInfo.want_ipaddr;
else if (len > 15)
LogPrintf(LogWARN, "ParseAddr: %s: Bad address\n", *argv);
else {
char s[16];
strncpy(s, *argv, len);
s[len] = '\0';
if (inet_aton(s, paddr) == 0) {
LogPrintf(LogWARN, "ParseAddr: %s: Bad address\n", s);
return (0);
}
}
if (cp && *++cp) {
bits = strtol(cp, &wp, 0);
if (cp == wp || bits < 0 || bits > 32) {
LogPrintf(LogWARN, "ParseAddr: bad mask width.\n");
return (0);
}
} else {
/* if width is not given, assume whole 32 bits are meaningfull */
bits = 32;
}
if (pwidth)
*pwidth = bits;
if (pmask)
pmask->s_addr = htonl(netmasks[bits]);
return (1);
}
static int
ParseProto(int argc, char const *const *argv)
{
int proto;
if (argc < 1)
return (P_NONE);
if (!strcmp(*argv, "tcp"))
proto = P_TCP;
else if (!strcmp(*argv, "udp"))
proto = P_UDP;
else if (!strcmp(*argv, "icmp"))
proto = P_ICMP;
else
proto = P_NONE;
return (proto);
}
static int
ParsePort(const char *service, int proto)
{
const char *protocol_name;
char *cp;
struct servent *servent;
int port;
switch (proto) {
case P_UDP:
protocol_name = "udp";
break;
case P_TCP:
protocol_name = "tcp";
break;
default:
protocol_name = 0;
}
servent = getservbyname(service, protocol_name);
if (servent != 0)
return (ntohs(servent->s_port));
port = strtol(service, &cp, 0);
if (cp == service) {
LogPrintf(LogWARN, "ParsePort: %s is not a port name or number.\n",
service);
return (0);
}
return (port);
}
/*
* ICMP Syntax: src eq icmp_message_type
*/
static int
ParseIcmp(int argc, char const *const *argv)
{
int type;
char *cp;
switch (argc) {
case 0:
/* permit/deny all ICMP types */
filterdata.opt.srcop = OP_NONE;
break;
default:
LogPrintf(LogWARN, "ParseIcmp: bad icmp syntax.\n");
return (0);
case 3:
if (!strcmp(*argv, "src") && !strcmp(argv[1], "eq")) {
type = strtol(argv[2], &cp, 0);
if (cp == argv[2]) {
LogPrintf(LogWARN, "ParseIcmp: type is expected.\n");
return (0);
}
filterdata.opt.srcop = OP_EQ;
filterdata.opt.srcport = type;
}
break;
}
return (1);
}
static int
ParseOp(const char *cp)
{
int op = OP_NONE;
if (!strcmp(cp, "eq"))
op = OP_EQ;
else if (!strcmp(cp, "gt"))
op = OP_GT;
else if (!strcmp(cp, "lt"))
op = OP_LT;
return (op);
}
/*
* UDP Syntax: [src op port] [dst op port]
*/
static int
ParseUdpOrTcp(int argc, char const *const *argv, int proto)
{
filterdata.opt.srcop = filterdata.opt.dstop = OP_NONE;
filterdata.opt.estab = 0;
if (argc == 0) {
/* permit/deny all tcp traffic */
return (1);
}
if (argc >= 3 && !strcmp(*argv, "src")) {
filterdata.opt.srcop = ParseOp(argv[1]);
if (filterdata.opt.srcop == OP_NONE) {
LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n");
return (0);
}
filterdata.opt.srcport = ParsePort(argv[2], proto);
if (filterdata.opt.srcport == 0)
return (0);
argc -= 3;
argv += 3;
if (argc == 0)
return (1);
}
if (argc >= 3 && !strcmp(argv[0], "dst")) {
filterdata.opt.dstop = ParseOp(argv[1]);
if (filterdata.opt.dstop == OP_NONE) {
LogPrintf(LogWARN, "ParseUdpOrTcp: bad operation\n");
return (0);
}
filterdata.opt.dstport = ParsePort(argv[2], proto);
if (filterdata.opt.dstport == 0)
return (0);
argc -= 3;
argv += 3;
if (argc == 0)
return (1);
}
if (argc == 1 && proto == P_TCP) {
if (!strcmp(*argv, "estab")) {
filterdata.opt.estab = 1;
return (1);
}
LogPrintf(LogWARN, "ParseUdpOrTcp: estab is expected: %s\n", *argv);
return (0);
}
if (argc > 0)
LogPrintf(LogWARN, "ParseUdpOrTcp: bad src/dst port syntax: %s\n", *argv);
return (0);
}
static const char *opname[] = {"none", "eq", "gt", NULL, "lt"};
static int
Parse(int argc, char const *const *argv, struct filterent * ofp)
{
int action, proto;
int val;
char *wp;
struct filterent *fp = &filterdata;
val = strtol(*argv, &wp, 0);
if (*argv == wp || val > MAXFILTERS) {
LogPrintf(LogWARN, "Parse: invalid filter number.\n");
return (0);
}
if (val < 0) {
for (val = 0; val < MAXFILTERS; val++) {
ofp->action = A_NONE;
ofp++;
}
LogPrintf(LogWARN, "Parse: filter cleared.\n");
return (1);
}
ofp += val;
if (--argc == 0) {
LogPrintf(LogWARN, "Parse: missing action.\n");
return (0);
}
argv++;
proto = P_NONE;
memset(&filterdata, '\0', sizeof filterdata);
if (!strcmp(*argv, "permit")) {
action = A_PERMIT;
} else if (!strcmp(*argv, "deny")) {
action = A_DENY;
} else if (!strcmp(*argv, "clear")) {
ofp->action = A_NONE;
return (1);
} else {
LogPrintf(LogWARN, "Parse: bad action: %s\n", *argv);
return (0);
}
fp->action = action;
argc--;
argv++;
if (fp->action == A_DENY) {
if (!strcmp(*argv, "host")) {
fp->action |= A_UHOST;
argc--;
argv++;
} else if (!strcmp(*argv, "port")) {
fp->action |= A_UPORT;
argc--;
argv++;
}
}
proto = ParseProto(argc, argv);
if (proto == P_NONE) {
if (ParseAddr(argc, argv, &fp->saddr, &fp->smask, &fp->swidth)) {
argc--;
argv++;
proto = ParseProto(argc, argv);
if (proto == P_NONE) {
if (ParseAddr(argc, argv, &fp->daddr, &fp->dmask, &fp->dwidth)) {
argc--;
argv++;
}
proto = ParseProto(argc, argv);
if (proto != P_NONE) {
argc--;
argv++;
}
} else {
argc--;
argv++;
}
} else {
LogPrintf(LogWARN, "Parse: Address/protocol expected.\n");
return (0);
}
} else {
argc--;
argv++;
}
val = 1;
fp->proto = proto;
switch (proto) {
case P_TCP:
val = ParseUdpOrTcp(argc, argv, P_TCP);
break;
case P_UDP:
val = ParseUdpOrTcp(argc, argv, P_UDP);
break;
case P_ICMP:
val = ParseIcmp(argc, argv);
break;
}
LogPrintf(LogDEBUG, "Parse: Src: %s\n", inet_ntoa(fp->saddr));
LogPrintf(LogDEBUG, "Parse: Src mask: %s\n", inet_ntoa(fp->smask));
LogPrintf(LogDEBUG, "Parse: Dst: %s\n", inet_ntoa(fp->daddr));
LogPrintf(LogDEBUG, "Parse: Dst mask: %s\n", inet_ntoa(fp->dmask));
LogPrintf(LogDEBUG, "Parse: Proto = %d\n", proto);
LogPrintf(LogDEBUG, "Parse: src: %s (%d)\n", opname[fp->opt.srcop],
fp->opt.srcport);
LogPrintf(LogDEBUG, "Parse: dst: %s (%d)\n", opname[fp->opt.dstop],
fp->opt.dstport);
LogPrintf(LogDEBUG, "Parse: estab: %d\n", fp->opt.estab);
if (val)
*ofp = *fp;
return (val);
}
int
SetIfilter(struct cmdargs const *arg)
{
if (arg->argc > 0) {
Parse(arg->argc, arg->argv, ifilters);
return 0;
}
return -1;
}
int
SetOfilter(struct cmdargs const *arg)
{
if (arg->argc > 0) {
(void) Parse(arg->argc, arg->argv, ofilters);
return 0;
}
return -1;
}
int
SetDfilter(struct cmdargs const *arg)
{
if (arg->argc > 0) {
(void) Parse(arg->argc, arg->argv, dfilters);
return 0;
}
return -1;
}
int
SetAfilter(struct cmdargs const *arg)
{
if (arg->argc > 0) {
(void) Parse(arg->argc, arg->argv, afilters);
return 0;
}
return -1;
}
static const char *protoname[] = { "none", "tcp", "udp", "icmp" };
static const char *actname[] = { "none ", "permit ", "deny " };
static void
ShowFilter(struct filterent * fp)
{
int n;
if (!VarTerm)
return;
for (n = 0; n < MAXFILTERS; n++, fp++) {
if (fp->action != A_NONE) {
fprintf(VarTerm, "%2d %s", n, actname[fp->action & (A_PERMIT|A_DENY)]);
if (fp->action & A_UHOST)
fprintf(VarTerm, "host ");
else if (fp->action & A_UPORT)
fprintf(VarTerm, "port ");
else
fprintf(VarTerm, " ");
fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->saddr), fp->swidth);
fprintf(VarTerm, "%s/%d ", inet_ntoa(fp->daddr), fp->dwidth);
if (fp->proto) {
fprintf(VarTerm, "%s", protoname[fp->proto]);
if (fp->opt.srcop)
fprintf(VarTerm, " src %s %d", opname[fp->opt.srcop],
fp->opt.srcport);
if (fp->opt.dstop)
fprintf(VarTerm, " dst %s %d", opname[fp->opt.dstop],
fp->opt.dstport);
if (fp->opt.estab)
fprintf(VarTerm, " estab");
}
fprintf(VarTerm, "\n");
}
}
}
int
ShowIfilter(struct cmdargs const *arg)
{
ShowFilter(ifilters);
return 0;
}
int
ShowOfilter(struct cmdargs const *arg)
{
ShowFilter(ofilters);
return 0;
}
int
ShowDfilter(struct cmdargs const *arg)
{
ShowFilter(dfilters);
return 0;
}
int
ShowAfilter(struct cmdargs const *arg)
{
ShowFilter(afilters);
return 0;
}

87
usr.sbin/ppp/filter.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: filter.h,v 1.10 1997/10/26 01:02:35 brian Exp $
*
* TODO:
*/
/*
* Actions
*/
#define A_NONE 0
#define A_PERMIT 1
#define A_DENY 2
#define A_MASK 3
#define A_UHOST 4
#define A_UPORT 8
/*
* Known protocols
*/
#define P_NONE 0
#define P_TCP 1
#define P_UDP 2
#define P_ICMP 3
/*
* Operations
*/
#define OP_NONE 0
#define OP_EQ 1
#define OP_GT 2
#define OP_LT 4
struct filterent {
int action; /* Filtering action */
int swidth; /* Effective source address width */
struct in_addr saddr; /* Source address */
struct in_addr smask; /* Source address mask */
int dwidth; /* Effective destination address width */
struct in_addr daddr; /* Destination address */
struct in_addr dmask; /* Destination address mask */
int proto; /* Protocol */
struct {
short srcop;
u_short srcport;
short dstop;
u_short dstport;
int estab;
} opt;
};
#define MAXFILTERS 20
#define FL_IN 0
#define FL_OUT 1
#define FL_DIAL 2
#define FL_KEEP 3
extern struct filterent ifilters[MAXFILTERS]; /* incoming packet filter */
extern struct filterent ofilters[MAXFILTERS]; /* outgoing packet filter */
extern struct filterent dfilters[MAXFILTERS]; /* dial-out packet filter */
extern struct filterent afilters[MAXFILTERS]; /* keep-alive packet filter */
extern int ParseAddr(int, char const *const *, struct in_addr *, struct in_addr *, int *);
extern int ShowIfilter(struct cmdargs const *);
extern int ShowOfilter(struct cmdargs const *);
extern int ShowDfilter(struct cmdargs const *);
extern int ShowAfilter(struct cmdargs const *);
extern int SetIfilter(struct cmdargs const *);
extern int SetOfilter(struct cmdargs const *);
extern int SetDfilter(struct cmdargs const *);
extern int SetAfilter(struct cmdargs const *);

820
usr.sbin/ppp/fsm.c Normal file
View File

@ -0,0 +1,820 @@
/*
* PPP Finite State Machine for LCP/IPCP
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: fsm.c,v 1.26 1998/01/10 01:55:09 brian Exp $
*
* TODO:
* o Refer loglevel for log output
* o Better option log display
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "hdlc.h"
#include "lqr.h"
#include "lcpproto.h"
#include "lcp.h"
#include "ccp.h"
#include "modem.h"
#include "loadalias.h"
#include "vars.h"
u_char AckBuff[200];
u_char NakBuff[200];
u_char RejBuff[100];
u_char ReqBuff[200];
u_char *ackp = NULL;
u_char *nakp = NULL;
u_char *rejp = NULL;
static void FsmSendConfigReq(struct fsm *);
static void FsmSendTerminateReq(struct fsm *);
static void FsmInitRestartCounter(struct fsm *);
char const *StateNames[] = {
"Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",
"Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",
};
static void
StoppedTimeout(void *v)
{
struct fsm *fp = (struct fsm *)v;
LogPrintf(fp->LogLevel, "Stopped timer expired\n");
if (fp->OpenTimer.state == TIMER_RUNNING) {
LogPrintf(LogWARN, "%s: aborting open delay due to stopped timer\n",
fp->name);
StopTimer(&fp->OpenTimer);
}
if (modem != -1)
DownConnection();
else
FsmDown(fp);
}
void
FsmInit(struct fsm * fp)
{
LogPrintf(LogDEBUG, "FsmInit\n");
fp->state = ST_INITIAL;
fp->reqid = 1;
fp->restart = 1;
fp->maxconfig = 3;
}
static void
NewState(struct fsm * fp, int new)
{
LogPrintf(fp->LogLevel, "State change %s --> %s\n",
StateNames[fp->state], StateNames[new]);
if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)
StopTimer(&fp->StoppedTimer);
fp->state = new;
if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {
StopTimer(&fp->FsmTimer);
if (new == ST_STOPPED && fp->StoppedTimer.load) {
fp->StoppedTimer.state = TIMER_STOPPED;
fp->StoppedTimer.func = StoppedTimeout;
fp->StoppedTimer.arg = (void *) fp;
StartTimer(&fp->StoppedTimer);
}
}
}
void
FsmOutput(struct fsm * fp, u_int code, u_int id, u_char * ptr, int count)
{
int plen;
struct fsmheader lh;
struct mbuf *bp;
plen = sizeof(struct fsmheader) + count;
lh.code = code;
lh.id = id;
lh.length = htons(plen);
bp = mballoc(plen, MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
if (count)
memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
LogDumpBp(LogDEBUG, "FsmOutput", bp);
HdlcOutput(PRI_LINK, fp->proto, bp);
}
static void
FsmOpenNow(void *v)
{
struct fsm *fp = (struct fsm *)v;
StopTimer(&fp->OpenTimer);
if (fp->state <= ST_STOPPED) {
FsmInitRestartCounter(fp);
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
}
}
void
FsmOpen(struct fsm * fp)
{
switch (fp->state) {
case ST_INITIAL:
(fp->LayerStart) (fp);
NewState(fp, ST_STARTING);
break;
case ST_STARTING:
break;
case ST_CLOSED:
if (fp->open_mode == OPEN_PASSIVE) {
NewState(fp, ST_STOPPED);
} else if (fp->open_mode > 0) {
if (fp->open_mode > 1)
LogPrintf(LogPHASE, "Entering STOPPED state for %d seconds\n",
fp->open_mode);
NewState(fp, ST_STOPPED);
fp->OpenTimer.state = TIMER_STOPPED;
fp->OpenTimer.load = fp->open_mode * SECTICKS;
fp->OpenTimer.func = FsmOpenNow;
fp->OpenTimer.arg = (void *)fp;
StartTimer(&fp->OpenTimer);
} else
FsmOpenNow(fp);
break;
case ST_STOPPED: /* XXX: restart option */
case ST_REQSENT:
case ST_ACKRCVD:
case ST_ACKSENT:
case ST_OPENED: /* XXX: restart option */
break;
case ST_CLOSING: /* XXX: restart option */
case ST_STOPPING: /* XXX: restart option */
NewState(fp, ST_STOPPING);
break;
}
}
void
FsmUp(struct fsm * fp)
{
switch (fp->state) {
case ST_INITIAL:
NewState(fp, ST_CLOSED);
break;
case ST_STARTING:
FsmInitRestartCounter(fp);
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
default:
LogPrintf(fp->LogLevel, "Oops, Up at %s\n", StateNames[fp->state]);
break;
}
}
void
FsmDown(struct fsm * fp)
{
switch (fp->state) {
case ST_CLOSED:
case ST_CLOSING:
NewState(fp, ST_INITIAL);
break;
case ST_STOPPED:
(fp->LayerStart) (fp);
/* Fall into.. */
case ST_STOPPING:
case ST_REQSENT:
case ST_ACKRCVD:
case ST_ACKSENT:
NewState(fp, ST_STARTING);
break;
case ST_OPENED:
(fp->LayerDown) (fp);
NewState(fp, ST_STARTING);
break;
}
}
void
FsmClose(struct fsm * fp)
{
switch (fp->state) {
case ST_STARTING:
NewState(fp, ST_INITIAL);
break;
case ST_STOPPED:
NewState(fp, ST_CLOSED);
break;
case ST_STOPPING:
NewState(fp, ST_CLOSING);
break;
case ST_OPENED:
(fp->LayerDown) (fp);
/* Fall down */
case ST_REQSENT:
case ST_ACKRCVD:
case ST_ACKSENT:
FsmInitRestartCounter(fp);
FsmSendTerminateReq(fp);
NewState(fp, ST_CLOSING);
break;
}
}
/*
* Send functions
*/
static void
FsmSendConfigReq(struct fsm * fp)
{
if (--fp->maxconfig > 0) {
(fp->SendConfigReq) (fp);
StartTimer(&fp->FsmTimer); /* Start restart timer */
fp->restart--; /* Decrement restart counter */
} else {
FsmClose(fp);
}
}
static void
FsmSendTerminateReq(struct fsm * fp)
{
LogPrintf(fp->LogLevel, "SendTerminateReq.\n");
FsmOutput(fp, CODE_TERMREQ, fp->reqid++, NULL, 0);
(fp->SendTerminateReq) (fp);
StartTimer(&fp->FsmTimer); /* Start restart timer */
fp->restart--; /* Decrement restart counter */
}
static void
FsmSendConfigAck(struct fsm * fp,
struct fsmheader * lhp,
u_char * option,
int count)
{
LogPrintf(fp->LogLevel, "SendConfigAck(%s)\n", StateNames[fp->state]);
(fp->DecodeConfig) (option, count, MODE_NOP);
FsmOutput(fp, CODE_CONFIGACK, lhp->id, option, count);
}
static void
FsmSendConfigRej(struct fsm * fp,
struct fsmheader * lhp,
u_char * option,
int count)
{
LogPrintf(fp->LogLevel, "SendConfigRej(%s)\n", StateNames[fp->state]);
(fp->DecodeConfig) (option, count, MODE_NOP);
FsmOutput(fp, CODE_CONFIGREJ, lhp->id, option, count);
}
static void
FsmSendConfigNak(struct fsm * fp,
struct fsmheader * lhp,
u_char * option,
int count)
{
LogPrintf(fp->LogLevel, "SendConfigNak(%s)\n", StateNames[fp->state]);
(fp->DecodeConfig) (option, count, MODE_NOP);
FsmOutput(fp, CODE_CONFIGNAK, lhp->id, option, count);
}
/*
* Timeout actions
*/
static void
FsmTimeout(void *v)
{
struct fsm *fp = (struct fsm *)v;
if (fp->restart) {
switch (fp->state) {
case ST_CLOSING:
case ST_STOPPING:
FsmSendTerminateReq(fp);
break;
case ST_REQSENT:
case ST_ACKSENT:
FsmSendConfigReq(fp);
break;
case ST_ACKRCVD:
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
}
StartTimer(&fp->FsmTimer);
} else {
switch (fp->state) {
case ST_CLOSING:
NewState(fp, ST_CLOSED);
(fp->LayerFinish) (fp);
break;
case ST_STOPPING:
NewState(fp, ST_STOPPED);
(fp->LayerFinish) (fp);
break;
case ST_REQSENT: /* XXX: 3p */
case ST_ACKSENT:
case ST_ACKRCVD:
NewState(fp, ST_STOPPED);
(fp->LayerFinish) (fp);
break;
}
}
}
static void
FsmInitRestartCounter(struct fsm * fp)
{
StopTimer(&fp->FsmTimer);
fp->FsmTimer.state = TIMER_STOPPED;
fp->FsmTimer.func = FsmTimeout;
fp->FsmTimer.arg = (void *) fp;
(fp->InitRestartCounter) (fp);
}
/*
* Actions when receive packets
*/
static void
FsmRecvConfigReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
/* RCR */
{
int plen, flen;
int ackaction = 0;
plen = plength(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
LogPrintf(LogERROR, "FsmRecvConfigReq: plen (%d) < flen (%d)\n",
plen, flen);
pfree(bp);
return;
}
/*
* Check and process easy case
*/
switch (fp->state) {
case ST_INITIAL:
case ST_STARTING:
LogPrintf(fp->LogLevel, "Oops, RCR in %s.\n", StateNames[fp->state]);
pfree(bp);
return;
case ST_CLOSED:
(fp->SendTerminateAck) (fp);
pfree(bp);
return;
case ST_CLOSING:
LogPrintf(fp->LogLevel, "Error: Got ConfigReq while state = %d\n",
fp->state);
case ST_STOPPING:
pfree(bp);
return;
}
(fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REQ);
if (nakp == NakBuff && rejp == RejBuff)
ackaction = 1;
switch (fp->state) {
case ST_OPENED:
(fp->LayerDown) (fp);
FsmSendConfigReq(fp);
break;
case ST_STOPPED:
FsmInitRestartCounter(fp);
FsmSendConfigReq(fp);
break;
}
if (rejp != RejBuff)
FsmSendConfigRej(fp, lhp, RejBuff, rejp - RejBuff);
if (nakp != NakBuff)
FsmSendConfigNak(fp, lhp, NakBuff, nakp - NakBuff);
if (ackaction)
FsmSendConfigAck(fp, lhp, AckBuff, ackp - AckBuff);
switch (fp->state) {
case ST_STOPPED:
case ST_OPENED:
if (ackaction)
NewState(fp, ST_ACKSENT);
else
NewState(fp, ST_REQSENT);
break;
case ST_REQSENT:
if (ackaction)
NewState(fp, ST_ACKSENT);
break;
case ST_ACKRCVD:
if (ackaction) {
NewState(fp, ST_OPENED);
(fp->LayerUp) (fp);
}
break;
case ST_ACKSENT:
if (!ackaction)
NewState(fp, ST_REQSENT);
break;
}
pfree(bp);
}
static void
FsmRecvConfigAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
/* RCA */
{
switch (fp->state) {
case ST_CLOSED:
case ST_STOPPED:
(fp->SendTerminateAck) (fp);
break;
case ST_CLOSING:
case ST_STOPPING:
break;
case ST_REQSENT:
FsmInitRestartCounter(fp);
NewState(fp, ST_ACKRCVD);
break;
case ST_ACKRCVD:
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
case ST_ACKSENT:
FsmInitRestartCounter(fp);
NewState(fp, ST_OPENED);
(fp->LayerUp) (fp);
break;
case ST_OPENED:
(fp->LayerDown) (fp);
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
}
pfree(bp);
}
static void
FsmRecvConfigNak(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
/* RCN */
{
int plen, flen;
plen = plength(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
pfree(bp);
return;
}
/*
* Check and process easy case
*/
switch (fp->state) {
case ST_INITIAL:
case ST_STARTING:
LogPrintf(fp->LogLevel, "Oops, RCN in %s.\n", StateNames[fp->state]);
pfree(bp);
return;
case ST_CLOSED:
case ST_STOPPED:
(fp->SendTerminateAck) (fp);
pfree(bp);
return;
case ST_CLOSING:
case ST_STOPPING:
pfree(bp);
return;
}
(fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_NAK);
switch (fp->state) {
case ST_REQSENT:
case ST_ACKSENT:
FsmInitRestartCounter(fp);
FsmSendConfigReq(fp);
break;
case ST_OPENED:
(fp->LayerDown) (fp);
/* Fall down */
case ST_ACKRCVD:
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
}
pfree(bp);
}
static void
FsmRecvTermReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
/* RTR */
{
switch (fp->state) {
case ST_INITIAL:
case ST_STARTING:
LogPrintf(fp->LogLevel, "Oops, RTR in %s\n", StateNames[fp->state]);
break;
case ST_CLOSED:
case ST_STOPPED:
case ST_CLOSING:
case ST_STOPPING:
case ST_REQSENT:
(fp->SendTerminateAck) (fp);
break;
case ST_ACKRCVD:
case ST_ACKSENT:
(fp->SendTerminateAck) (fp);
NewState(fp, ST_REQSENT);
break;
case ST_OPENED:
(fp->LayerDown) (fp);
(fp->SendTerminateAck) (fp);
StartTimer(&fp->FsmTimer); /* Start restart timer */
fp->restart = 0;
NewState(fp, ST_STOPPING);
break;
}
pfree(bp);
}
static void
FsmRecvTermAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
/* RTA */
{
switch (fp->state) {
case ST_CLOSING:
NewState(fp, ST_CLOSED);
(fp->LayerFinish) (fp);
break;
case ST_STOPPING:
NewState(fp, ST_STOPPED);
(fp->LayerFinish) (fp);
break;
case ST_ACKRCVD:
NewState(fp, ST_REQSENT);
break;
case ST_OPENED:
(fp->LayerDown) (fp);
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
}
pfree(bp);
}
static void
FsmRecvConfigRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
/* RCJ */
{
int plen, flen;
plen = plength(bp);
flen = ntohs(lhp->length) - sizeof *lhp;
if (plen < flen) {
pfree(bp);
return;
}
LogPrintf(fp->LogLevel, "RecvConfigRej.\n");
/*
* Check and process easy case
*/
switch (fp->state) {
case ST_INITIAL:
case ST_STARTING:
LogPrintf(fp->LogLevel, "Oops, RCJ in %s.\n", StateNames[fp->state]);
pfree(bp);
return;
case ST_CLOSED:
case ST_STOPPED:
(fp->SendTerminateAck) (fp);
pfree(bp);
return;
case ST_CLOSING:
case ST_STOPPING:
pfree(bp);
return;
}
(fp->DecodeConfig) (MBUF_CTOP(bp), flen, MODE_REJ);
switch (fp->state) {
case ST_REQSENT:
case ST_ACKSENT:
FsmInitRestartCounter(fp);
FsmSendConfigReq(fp);
break;
case ST_OPENED:
(fp->LayerDown) (fp);
/* Fall down */
case ST_ACKRCVD:
FsmSendConfigReq(fp);
NewState(fp, ST_REQSENT);
break;
}
pfree(bp);
}
static void
FsmRecvCodeRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
LogPrintf(fp->LogLevel, "RecvCodeRej\n");
pfree(bp);
}
static void
FsmRecvProtoRej(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
u_short *sp, proto;
sp = (u_short *) MBUF_CTOP(bp);
proto = ntohs(*sp);
LogPrintf(fp->LogLevel, "-- Protocol (%04x) was rejected.\n", proto);
switch (proto) {
case PROTO_LQR:
StopLqr(LQM_LQR);
break;
case PROTO_CCP:
fp = &CcpFsm;
(fp->LayerFinish) (fp);
switch (fp->state) {
case ST_CLOSED:
case ST_CLOSING:
NewState(fp, ST_CLOSED);
default:
NewState(fp, ST_STOPPED);
break;
}
break;
}
pfree(bp);
}
static void
FsmRecvEchoReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
u_char *cp;
u_long *lp, magic;
cp = MBUF_CTOP(bp);
lp = (u_long *) cp;
magic = ntohl(*lp);
if (magic != LcpInfo.his_magic) {
LogPrintf(LogERROR, "RecvEchoReq: his magic is bad!!\n");
/* XXX: We should send terminate request */
}
if (fp->state == ST_OPENED) {
*lp = htonl(LcpInfo.want_magic); /* Insert local magic number */
LogPrintf(fp->LogLevel, "SendEchoRep(%s)\n", StateNames[fp->state]);
FsmOutput(fp, CODE_ECHOREP, lhp->id, cp, plength(bp));
}
pfree(bp);
}
static void
FsmRecvEchoRep(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
u_long *lp, magic;
lp = (u_long *) MBUF_CTOP(bp);
magic = ntohl(*lp);
/*
* Tolerate echo replies with either magic number
*/
if (magic != 0 && magic != LcpInfo.his_magic && magic != LcpInfo.want_magic) {
LogPrintf(LogERROR, "RecvEchoRep: his magic is wrong! expect: %x got: %x\n",
LcpInfo.his_magic, magic);
/*
* XXX: We should send terminate request. But poor implementation may die
* as a result.
*/
}
RecvEchoLqr(bp);
pfree(bp);
}
static void
FsmRecvDiscReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
LogPrintf(fp->LogLevel, "RecvDiscReq\n");
pfree(bp);
}
static void
FsmRecvIdent(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
LogPrintf(fp->LogLevel, "RecvIdent\n");
pfree(bp);
}
static void
FsmRecvTimeRemain(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
LogPrintf(fp->LogLevel, "RecvTimeRemain\n");
pfree(bp);
}
static void
FsmRecvResetReq(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
LogPrintf(fp->LogLevel, "RecvResetReq(%d)\n", lhp->id);
CcpRecvResetReq(fp);
/*
* All sendable compressed packets are queued in the PRI_NORMAL modem
* output queue.... dump 'em to the priority queue so that they arrive
* at the peer before our ResetAck.
*/
SequenceQueues();
LogPrintf(fp->LogLevel, "SendResetAck(%d)\n", lhp->id);
FsmOutput(fp, CODE_RESETACK, lhp->id, NULL, 0);
pfree(bp);
}
static void
FsmRecvResetAck(struct fsm * fp, struct fsmheader * lhp, struct mbuf * bp)
{
LogPrintf(fp->LogLevel, "RecvResetAck(%d)\n", lhp->id);
CcpResetInput(lhp->id);
fp->reqid++;
pfree(bp);
}
static const struct fsmcodedesc FsmCodes[] = {
{FsmRecvConfigReq, "Configure Request",},
{FsmRecvConfigAck, "Configure Ack",},
{FsmRecvConfigNak, "Configure Nak",},
{FsmRecvConfigRej, "Configure Reject",},
{FsmRecvTermReq, "Terminate Request",},
{FsmRecvTermAck, "Terminate Ack",},
{FsmRecvCodeRej, "Code Reject",},
{FsmRecvProtoRej, "Protocol Reject",},
{FsmRecvEchoReq, "Echo Request",},
{FsmRecvEchoRep, "Echo Reply",},
{FsmRecvDiscReq, "Discard Request",},
{FsmRecvIdent, "Ident",},
{FsmRecvTimeRemain, "Time Remain",},
{FsmRecvResetReq, "Reset Request",},
{FsmRecvResetAck, "Reset Ack",},
};
void
FsmInput(struct fsm * fp, struct mbuf * bp)
{
int len;
struct fsmheader *lhp;
const struct fsmcodedesc *codep;
len = plength(bp);
if (len < sizeof(struct fsmheader)) {
pfree(bp);
return;
}
lhp = (struct fsmheader *) MBUF_CTOP(bp);
if (lhp->code == 0 || lhp->code > fp->max_code) {
pfree(bp); /* XXX: Should send code reject */
return;
}
bp->offset += sizeof(struct fsmheader);
bp->cnt -= sizeof(struct fsmheader);
codep = FsmCodes + lhp->code - 1;
LogPrintf(fp->LogLevel, "Received %s (%d) state = %s (%d)\n",
codep->name, lhp->id, StateNames[fp->state], fp->state);
if (LogIsKept(LogDEBUG))
LogMemory();
(codep->action) (fp, lhp, bp);
if (LogIsKept(LogDEBUG))
LogMemory();
}

132
usr.sbin/ppp/fsm.h Normal file
View File

@ -0,0 +1,132 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: fsm.h,v 1.15 1998/01/20 22:47:37 brian Exp $
*
* TODO:
*/
/*
* State of machine
*/
#define ST_INITIAL 0
#define ST_STARTING 1
#define ST_CLOSED 2
#define ST_STOPPED 3
#define ST_CLOSING 4
#define ST_STOPPING 5
#define ST_REQSENT 6
#define ST_ACKRCVD 7
#define ST_ACKSENT 8
#define ST_OPENED 9
#define ST_MAX 10
#define ST_UNDEF -1
#define MODE_REQ 0
#define MODE_NAK 1
#define MODE_REJ 2
#define MODE_NOP 3
#define MODE_ACK 4 /* pseudo mode for ccp negotiations */
#define OPEN_PASSIVE -1
struct fsm {
const char *name; /* Name of protocol */
u_short proto; /* Protocol number */
u_short max_code;
int open_mode;
int state; /* State of the machine */
u_char reqid; /* Next request id */
int restart; /* Restart counter value */
int maxconfig;
struct pppTimer FsmTimer; /* Restart Timer */
struct pppTimer OpenTimer; /* Delay before opening */
/*
* This timer times the ST_STOPPED state out after the given value
* (specified via "set stopped ..."). Although this isn't specified in the
* rfc, the rfc *does* say that "the application may use higher level
* timers to avoid deadlock". The StoppedTimer takes effect when the other
* side ABENDs rather than going into ST_ACKSENT (and sending the ACK),
* causing ppp to time out and drop into ST_STOPPED. At this point,
* nothing will change this state :-(
*/
struct pppTimer StoppedTimer;
int LogLevel;
void (*LayerUp) (struct fsm *);
void (*LayerDown) (struct fsm *);
void (*LayerStart) (struct fsm *);
void (*LayerFinish) (struct fsm *);
void (*InitRestartCounter) (struct fsm *);
void (*SendConfigReq) (struct fsm *);
void (*SendTerminateReq) (struct fsm *);
void (*SendTerminateAck) (struct fsm *);
void (*DecodeConfig) (u_char *, int, int);
};
struct fsmheader {
u_char code; /* Request code */
u_char id; /* Identification */
u_short length; /* Length of packet */
};
#define CODE_CONFIGREQ 1
#define CODE_CONFIGACK 2
#define CODE_CONFIGNAK 3
#define CODE_CONFIGREJ 4
#define CODE_TERMREQ 5
#define CODE_TERMACK 6
#define CODE_CODEREJ 7
#define CODE_PROTOREJ 8
#define CODE_ECHOREQ 9 /* Used in LCP */
#define CODE_ECHOREP 10 /* Used in LCP */
#define CODE_DISCREQ 11
#define CODE_IDENT 12 /* Used in LCP Extension */
#define CODE_TIMEREM 13 /* Used in LCP Extension */
#define CODE_RESETREQ 14 /* Used in CCP */
#define CODE_RESETACK 15 /* Used in CCP */
struct fsmcodedesc {
void (*action) (struct fsm *, struct fsmheader *, struct mbuf *);
const char *name;
};
struct fsmconfig {
u_char type;
u_char length;
};
extern u_char AckBuff[200];
extern u_char NakBuff[200];
extern u_char RejBuff[100];
extern u_char ReqBuff[200];
extern u_char *ackp;
extern u_char *nakp;
extern u_char *rejp;
extern char const *StateNames[];
extern void FsmInit(struct fsm *);
extern void FsmOutput(struct fsm *, u_int, u_int, u_char *, int);
extern void FsmOpen(struct fsm *);
extern void FsmUp(struct fsm *);
extern void FsmDown(struct fsm *);
extern void FsmInput(struct fsm *, struct mbuf *);
extern void FsmClose(struct fsm *);

576
usr.sbin/ppp/hdlc.c Normal file
View File

@ -0,0 +1,576 @@
/*
* PPP High Level Link Control (HDLC) Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: hdlc.c,v 1.27 1998/01/10 01:55:10 brian Exp $
*
* TODO:
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "hdlc.h"
#include "lcpproto.h"
#include "ipcp.h"
#include "ip.h"
#include "vjcomp.h"
#include "pap.h"
#include "chap.h"
#include "lcp.h"
#include "async.h"
#include "lqr.h"
#include "loadalias.h"
#include "vars.h"
#include "modem.h"
#include "ccp.h"
static struct hdlcstat {
int badfcs;
int badaddr;
int badcommand;
int unknownproto;
} HdlcStat;
static int ifOutPackets;
static int ifOutOctets;
static int ifOutLQRs;
static struct protostat {
u_short number;
const char *name;
u_long in_count;
u_long out_count;
} ProtocolStat[] = {
{ PROTO_IP, "IP" },
{ PROTO_VJUNCOMP, "VJ_UNCOMP" },
{ PROTO_VJCOMP, "VJ_COMP" },
{ PROTO_COMPD, "COMPD" },
{ PROTO_LCP, "LCP" },
{ PROTO_IPCP, "IPCP" },
{ PROTO_CCP, "CCP" },
{ PROTO_PAP, "PAP" },
{ PROTO_LQR, "LQR" },
{ PROTO_CHAP, "CHAP" },
{ 0, "Others" }
};
static u_short const fcstab[256] = {
/* 00 */ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
/* 08 */ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
/* 10 */ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
/* 18 */ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
/* 20 */ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
/* 28 */ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
/* 30 */ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
/* 38 */ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
/* 40 */ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
/* 48 */ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
/* 50 */ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
/* 58 */ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
/* 60 */ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
/* 68 */ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
/* 70 */ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
/* 78 */ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
/* 80 */ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
/* 88 */ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
/* 90 */ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
/* 98 */ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
/* a0 */ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
/* a8 */ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
/* b0 */ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
/* b8 */ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
/* c0 */ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
/* c8 */ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
/* d0 */ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
/* d8 */ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
/* e0 */ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
/* e8 */ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
/* f0 */ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
/* f8 */ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
u_char EscMap[33];
void
HdlcInit()
{
ifOutOctets = 0;
ifOutPackets = 0;
ifOutLQRs = 0;
}
/*
* HDLC FCS computation. Read RFC 1171 Appendix B and CCITT X.25 section
* 2.27 for further details.
*/
inline u_short
HdlcFcs(u_short fcs, u_char * cp, int len)
{
while (len--)
fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];
return (fcs);
}
static inline u_short
HdlcFcsBuf(u_short fcs, struct mbuf *m)
{
int len;
u_char *pos, *end;
len = plength(m);
pos = MBUF_CTOP(m);
end = pos + m->cnt;
while (len--) {
fcs = (fcs >> 8) ^ fcstab[(fcs ^ *pos++) & 0xff];
if (pos == end && len) {
m = m->next;
pos = MBUF_CTOP(m);
end = pos + m->cnt;
}
}
return (fcs);
}
void
HdlcOutput(int pri, u_short proto, struct mbuf * bp)
{
struct mbuf *mhp, *mfcs;
struct protostat *statp;
struct lqrdata *lqr;
u_char *cp;
u_short fcs;
if ((proto & 0xfff1) == 0x21) /* Network Layer protocol */
if (CcpFsm.state == ST_OPENED)
if (CcpOutput(pri, proto, bp))
return;
if (DEV_IS_SYNC)
mfcs = NULL;
else
mfcs = mballoc(2, MB_HDLCOUT);
mhp = mballoc(4, MB_HDLCOUT);
mhp->cnt = 0;
cp = MBUF_CTOP(mhp);
if (proto == PROTO_LCP || LcpInfo.his_acfcomp == 0) {
*cp++ = HDLC_ADDR;
*cp++ = HDLC_UI;
mhp->cnt += 2;
}
/*
* If possible, compress protocol field.
*/
if (LcpInfo.his_protocomp && (proto & 0xff00) == 0) {
*cp++ = proto;
mhp->cnt++;
} else {
*cp++ = proto >> 8;
*cp = proto & 0377;
mhp->cnt += 2;
}
mhp->next = bp;
while (bp->next != NULL)
bp = bp->next;
bp->next = mfcs;
bp = mhp->next;
lqr = &MyLqrData;
lqr->PeerOutPackets = ifOutPackets++;
ifOutOctets += plength(mhp) + 1;
lqr->PeerOutOctets = ifOutOctets;
if (proto == PROTO_LQR) {
lqr->MagicNumber = LcpInfo.want_magic;
lqr->LastOutLQRs = HisLqrData.PeerOutLQRs;
lqr->LastOutPackets = HisLqrData.PeerOutPackets;
lqr->LastOutOctets = HisLqrData.PeerOutOctets;
lqr->PeerInLQRs = HisLqrSave.SaveInLQRs;
lqr->PeerInPackets = HisLqrSave.SaveInPackets;
lqr->PeerInDiscards = HisLqrSave.SaveInDiscards;
lqr->PeerInErrors = HisLqrSave.SaveInErrors;
lqr->PeerInOctets = HisLqrSave.SaveInOctets;
lqr->PeerOutLQRs = ++ifOutLQRs;
LqrDump("LqrOutput", lqr);
LqrChangeOrder(lqr, (struct lqrdata *) (MBUF_CTOP(bp)));
}
if (!DEV_IS_SYNC) {
mfcs->cnt = 0;
fcs = HdlcFcsBuf(INITFCS, mhp);
fcs = ~fcs;
cp = MBUF_CTOP(mfcs);
*cp++ = fcs & 0377; /* Low byte first!! */
*cp++ = fcs >> 8;
mfcs->cnt = 2;
}
LogDumpBp(LogHDLC, "HdlcOutput", mhp);
for (statp = ProtocolStat; statp->number; statp++)
if (statp->number == proto)
break;
statp->out_count++;
LogPrintf(LogDEBUG, "HdlcOutput: proto = 0x%04x\n", proto);
if (DEV_IS_SYNC)
ModemOutput(pri, mhp);
else
AsyncOutput(pri, mhp, proto);
}
/* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
static struct {
u_short from;
u_short to;
const char *name;
} protocols[] = {
{ 0x0001, 0x0001, "Padding Protocol" },
{ 0x0003, 0x001f, "reserved (transparency inefficient)" },
{ 0x0021, 0x0021, "Internet Protocol" },
{ 0x0023, 0x0023, "OSI Network Layer" },
{ 0x0025, 0x0025, "Xerox NS IDP" },
{ 0x0027, 0x0027, "DECnet Phase IV" },
{ 0x0029, 0x0029, "Appletalk" },
{ 0x002b, 0x002b, "Novell IPX" },
{ 0x002d, 0x002d, "Van Jacobson Compressed TCP/IP" },
{ 0x002f, 0x002f, "Van Jacobson Uncompressed TCP/IP" },
{ 0x0031, 0x0031, "Bridging PDU" },
{ 0x0033, 0x0033, "Stream Protocol (ST-II)" },
{ 0x0035, 0x0035, "Banyan Vines" },
{ 0x0037, 0x0037, "reserved (until 1993)" },
{ 0x0039, 0x0039, "AppleTalk EDDP" },
{ 0x003b, 0x003b, "AppleTalk SmartBuffered" },
{ 0x003d, 0x003d, "Multi-Link" },
{ 0x003f, 0x003f, "NETBIOS Framing" },
{ 0x0041, 0x0041, "Cisco Systems" },
{ 0x0043, 0x0043, "Ascom Timeplex" },
{ 0x0045, 0x0045, "Fujitsu Link Backup and Load Balancing (LBLB)" },
{ 0x0047, 0x0047, "DCA Remote Lan" },
{ 0x0049, 0x0049, "Serial Data Transport Protocol (PPP-SDTP)" },
{ 0x004b, 0x004b, "SNA over 802.2" },
{ 0x004d, 0x004d, "SNA" },
{ 0x004f, 0x004f, "IP6 Header Compression" },
{ 0x0051, 0x0051, "KNX Bridging Data" },
{ 0x0053, 0x0053, "Encryption" },
{ 0x0055, 0x0055, "Individual Link Encryption" },
{ 0x006f, 0x006f, "Stampede Bridging" },
{ 0x0071, 0x0071, "BAP Bandwidth Allocation Protocol" },
{ 0x0073, 0x0073, "MP+ Protocol" },
{ 0x007d, 0x007d, "reserved (Control Escape)" },
{ 0x007f, 0x007f, "reserved (compression inefficient)" },
{ 0x00cf, 0x00cf, "reserved (PPP NLPID)" },
{ 0x00fb, 0x00fb, "compression on single link in multilink group" },
{ 0x00fd, 0x00fd, "1st choice compression" },
{ 0x00ff, 0x00ff, "reserved (compression inefficient)" },
{ 0x0200, 0x02ff, "(compression inefficient)" },
{ 0x0201, 0x0201, "802.1d Hello Packets" },
{ 0x0203, 0x0203, "IBM Source Routing BPDU" },
{ 0x0205, 0x0205, "DEC LANBridge100 Spanning Tree" },
{ 0x0207, 0x0207, "Cisco Discovery Protocol" },
{ 0x0209, 0x0209, "Netcs Twin Routing" },
{ 0x0231, 0x0231, "Luxcom" },
{ 0x0233, 0x0233, "Sigma Network Systems" },
{ 0x0235, 0x0235, "Apple Client Server Protocol" },
{ 0x1e00, 0x1eff, "(compression inefficient)" },
{ 0x4001, 0x4001, "Cray Communications Control Protocol" },
{ 0x4003, 0x4003, "CDPD Mobile Network Registration Protocol" },
{ 0x4021, 0x4021, "Stacker LZS" },
{ 0x8001, 0x801f, "Not Used - reserved" },
{ 0x8021, 0x8021, "Internet Protocol Control Protocol" },
{ 0x8023, 0x8023, "OSI Network Layer Control Protocol" },
{ 0x8025, 0x8025, "Xerox NS IDP Control Protocol" },
{ 0x8027, 0x8027, "DECnet Phase IV Control Protocol" },
{ 0x8029, 0x8029, "Appletalk Control Protocol" },
{ 0x802b, 0x802b, "Novell IPX Control Protocol" },
{ 0x802d, 0x802d, "reserved" },
{ 0x802f, 0x802f, "reserved" },
{ 0x8031, 0x8031, "Bridging NCP" },
{ 0x8033, 0x8033, "Stream Protocol Control Protocol" },
{ 0x8035, 0x8035, "Banyan Vines Control Protocol" },
{ 0x8037, 0x8037, "reserved till 1993" },
{ 0x8039, 0x8039, "reserved" },
{ 0x803b, 0x803b, "reserved" },
{ 0x803d, 0x803d, "Multi-Link Control Protocol" },
{ 0x803f, 0x803f, "NETBIOS Framing Control Protocol" },
{ 0x8041, 0x8041, "Cisco Systems Control Protocol" },
{ 0x8043, 0x8043, "Ascom Timeplex" },
{ 0x8045, 0x8045, "Fujitsu LBLB Control Protocol" },
{ 0x8047, 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" },
{ 0x8049, 0x8049, "Serial Data Control Protocol (PPP-SDCP)" },
{ 0x804b, 0x804b, "SNA over 802.2 Control Protocol" },
{ 0x804d, 0x804d, "SNA Control Protocol" },
{ 0x804f, 0x804f, "IP6 Header Compression Control Protocol" },
{ 0x8051, 0x8051, "KNX Bridging Control Protocol" },
{ 0x8053, 0x8053, "Encryption Control Protocol" },
{ 0x8055, 0x8055, "Individual Link Encryption Control Protocol" },
{ 0x806f, 0x806f, "Stampede Bridging Control Protocol" },
{ 0x8073, 0x8073, "MP+ Control Protocol" },
{ 0x8071, 0x8071, "BACP Bandwidth Allocation Control Protocol" },
{ 0x807d, 0x807d, "Not Used - reserved" },
{ 0x80cf, 0x80cf, "Not Used - reserved" },
{ 0x80fb, 0x80fb, "compression on single link in multilink group control" },
{ 0x80fd, 0x80fd, "Compression Control Protocol" },
{ 0x80ff, 0x80ff, "Not Used - reserved" },
{ 0x8207, 0x8207, "Cisco Discovery Protocol Control" },
{ 0x8209, 0x8209, "Netcs Twin Routing" },
{ 0x8235, 0x8235, "Apple Client Server Protocol Control" },
{ 0xc021, 0xc021, "Link Control Protocol" },
{ 0xc023, 0xc023, "Password Authentication Protocol" },
{ 0xc025, 0xc025, "Link Quality Report" },
{ 0xc027, 0xc027, "Shiva Password Authentication Protocol" },
{ 0xc029, 0xc029, "CallBack Control Protocol (CBCP)" },
{ 0xc081, 0xc081, "Container Control Protocol" },
{ 0xc223, 0xc223, "Challenge Handshake Authentication Protocol" },
{ 0xc225, 0xc225, "RSA Authentication Protocol" },
{ 0xc227, 0xc227, "Extensible Authentication Protocol" },
{ 0xc26f, 0xc26f, "Stampede Bridging Authorization Protocol" },
{ 0xc281, 0xc281, "Proprietary Authentication Protocol" },
{ 0xc283, 0xc283, "Proprietary Authentication Protocol" },
{ 0xc481, 0xc481, "Proprietary Node ID Authentication Protocol" }
};
#define NPROTOCOLS (sizeof protocols/sizeof protocols[0])
static const char *
Protocol2Nam(u_short proto)
{
int f;
for (f = 0; f < NPROTOCOLS; f++)
if (proto >= protocols[f].from && proto <= protocols[f].to)
return protocols[f].name;
else if (proto < protocols[f].from)
break;
return "unrecognised protocol";
}
static void
DecodePacket(u_short proto, struct mbuf * bp)
{
u_char *cp;
LogPrintf(LogDEBUG, "DecodePacket: proto = 0x%04x\n", proto);
/*
* If proto isn't PROTO_COMPD, we still want to pass it to the
* decompression routines so that the dictionary's updated
*/
if (CcpFsm.state == ST_OPENED)
if (proto == PROTO_COMPD) {
if ((bp = CompdInput(&proto, bp)) == NULL)
return;
} else if ((proto & 0xfff1) == 0x21) /* Network Layer protocol */
CcpDictSetup(proto, bp);
switch (proto) {
case PROTO_LCP:
LcpInput(bp);
break;
case PROTO_PAP:
PapInput(bp);
break;
case PROTO_LQR:
HisLqrSave.SaveInLQRs++;
LqrInput(bp);
break;
case PROTO_CHAP:
ChapInput(bp);
break;
case PROTO_VJUNCOMP:
case PROTO_VJCOMP:
bp = VjCompInput(bp, proto);
if (bp == NULL) {
break;
}
/* fall down */
case PROTO_IP:
IpInput(bp);
break;
case PROTO_IPCP:
IpcpInput(bp);
break;
case PROTO_CCP:
CcpInput(bp);
break;
default:
LogPrintf(LogPHASE, "Unknown protocol 0x%04x (%s)\n",
proto, Protocol2Nam(proto));
bp->offset -= 2;
bp->cnt += 2;
cp = MBUF_CTOP(bp);
LcpSendProtoRej(cp, bp->cnt);
HisLqrSave.SaveInDiscards++;
HdlcStat.unknownproto++;
pfree(bp);
break;
}
}
int
ReportProtStatus(struct cmdargs const *arg)
{
struct protostat *statp;
int cnt;
statp = ProtocolStat;
statp--;
cnt = 0;
fprintf(VarTerm, " Protocol in out Protocol in out\n");
do {
statp++;
fprintf(VarTerm, " %-9s: %8lu, %8lu",
statp->name, statp->in_count, statp->out_count);
if (++cnt == 2) {
fprintf(VarTerm, "\n");
cnt = 0;
}
} while (statp->number);
if (cnt)
fprintf(VarTerm, "\n");
return (0);
}
int
ReportHdlcStatus(struct cmdargs const *arg)
{
struct hdlcstat *hp = &HdlcStat;
if (VarTerm) {
fprintf(VarTerm, "HDLC level errors\n\n");
fprintf(VarTerm, "FCS: %u ADDR: %u COMMAND: %u PROTO: %u\n",
hp->badfcs, hp->badaddr, hp->badcommand, hp->unknownproto);
}
return 0;
}
static struct hdlcstat laststat;
void
HdlcErrorCheck()
{
struct hdlcstat *hp = &HdlcStat;
struct hdlcstat *op = &laststat;
if (memcmp(hp, op, sizeof laststat)) {
LogPrintf(LogPHASE, "HDLC errors -> FCS: %u ADDR: %u COMD: %u PROTO: %u\n",
hp->badfcs - op->badfcs, hp->badaddr - op->badaddr,
hp->badcommand - op->badcommand, hp->unknownproto - op->unknownproto);
}
laststat = HdlcStat;
}
void
HdlcInput(struct mbuf * bp)
{
u_short fcs, proto;
u_char *cp, addr, ctrl;
struct protostat *statp;
LogDumpBp(LogHDLC, "HdlcInput:", bp);
if (DEV_IS_SYNC)
fcs = GOODFCS;
else
fcs = HdlcFcs(INITFCS, MBUF_CTOP(bp), bp->cnt);
HisLqrSave.SaveInOctets += bp->cnt + 1;
LogPrintf(LogDEBUG, "HdlcInput: fcs = %04x (%s)\n",
fcs, (fcs == GOODFCS) ? "good" : "bad");
if (fcs != GOODFCS) {
HisLqrSave.SaveInErrors++;
LogPrintf(LogDEBUG, "HdlcInput: Bad FCS\n");
HdlcStat.badfcs++;
pfree(bp);
return;
}
if (!DEV_IS_SYNC)
bp->cnt -= 2; /* discard FCS part */
if (bp->cnt < 2) { /* XXX: raise this bar ? */
pfree(bp);
return;
}
cp = MBUF_CTOP(bp);
if (!LcpInfo.want_acfcomp) {
/*
* We expect that packet is not compressed.
*/
addr = *cp++;
if (addr != HDLC_ADDR) {
HisLqrSave.SaveInErrors++;
HdlcStat.badaddr++;
LogPrintf(LogDEBUG, "HdlcInput: addr %02x\n", *cp);
pfree(bp);
return;
}
ctrl = *cp++;
if (ctrl != HDLC_UI) {
HisLqrSave.SaveInErrors++;
HdlcStat.badcommand++;
LogPrintf(LogDEBUG, "HdlcInput: %02x\n", *cp);
pfree(bp);
return;
}
bp->offset += 2;
bp->cnt -= 2;
} else if (cp[0] == HDLC_ADDR && cp[1] == HDLC_UI) {
/*
* We can receive compressed packet, but peer still send uncompressed
* packet to me.
*/
cp += 2;
bp->offset += 2;
bp->cnt -= 2;
}
if (LcpInfo.want_protocomp) {
proto = 0;
cp--;
do {
cp++;
bp->offset++;
bp->cnt--;
proto = proto << 8;
proto += *cp;
} while (!(proto & 1));
} else {
proto = *cp++ << 8;
proto |= *cp++;
bp->offset += 2;
bp->cnt -= 2;
}
for (statp = ProtocolStat; statp->number; statp++)
if (statp->number == proto)
break;
statp->in_count++;
HisLqrSave.SaveInPackets++;
DecodePacket(proto, bp);
}

66
usr.sbin/ppp/hdlc.h Normal file
View File

@ -0,0 +1,66 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: hdlc.h,v 1.13 1997/12/03 10:23:48 brian Exp $
*
* TODO:
*/
/*
* Definition for Async HDLC
*/
#define HDLC_SYN 0x7e /* SYNC character */
#define HDLC_ESC 0x7d /* Escape character */
#define HDLC_XOR 0x20 /* Modifier value */
#define HDLC_ADDR 0xff
#define HDLC_UI 0x03
/*
* Definition for HDLC Frame Check Sequence
*/
#define INITFCS 0xffff /* Initial value for FCS computation */
#define GOODFCS 0xf0b8 /* Good FCS value */
#define DEF_MRU 1500
#define MAX_MRU 2048
#define MIN_MRU 296
#define DEF_MTU 0 /* whatever peer says */
#define MAX_MTU 2048
#define MIN_MTU 296
/*
* Output priority
*/
/* PRI_NORMAL and PRI_FAST have meaning only on the IP queue.
* All IP frames have the same priority once they are compressed.
* IP frames stay on the IP queue till they can be sent on the
* link. They are compressed at that time.
*/
#define PRI_NORMAL 0 /* Normal priority */
#define PRI_FAST 1 /* Fast (interractive) */
#define PRI_LINK 1 /* Urgent (LQR packets) */
extern u_char EscMap[33];
extern void HdlcInit(void);
extern void HdlcErrorCheck(void);
extern void HdlcInput(struct mbuf *);
extern void HdlcOutput(int, u_short, struct mbuf *bp);
extern u_short HdlcFcs(u_short, u_char *, int);
extern int ReportHdlcStatus(struct cmdargs const *);
extern int ReportProtStatus(struct cmdargs const *);

177
usr.sbin/ppp/id.c Normal file
View File

@ -0,0 +1,177 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: id.c,v 1.5 1997/12/27 19:23:12 brian Exp $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <sysexits.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "main.h"
#ifdef __OpenBSD__
#include <util.h>
#else
#include <libutil.h>
#endif
#include "id.h"
static int uid;
static int euid;
void
ID0init()
{
uid = getuid();
euid = geteuid();
}
static void
ID0setuser(void)
{
if (seteuid(uid) == -1) {
LogPrintf(LogERROR, "ID0setuser: Unable to seteuid!\n");
Cleanup(EX_NOPERM);
}
}
uid_t
ID0realuid()
{
return uid;
}
static void
ID0set0(void)
{
if (seteuid(euid) == -1) {
LogPrintf(LogERROR, "ID0set0: Unable to seteuid!\n");
Cleanup(EX_NOPERM);
}
}
int
ID0ioctl(int fd, unsigned long req, void *arg)
{
int ret;
ID0set0();
ret = ioctl(fd, req, arg);
LogPrintf(LogID0, "%d = ioctl(%d, %d, %p)\n", ret, fd, req, arg);
ID0setuser();
return ret;
}
int
ID0unlink(const char *name)
{
int ret;
ID0set0();
ret = unlink(name);
LogPrintf(LogID0, "%d = unlink(\"%s\")\n", ret, name);
ID0setuser();
return ret;
}
int
ID0socket(int domain, int type, int protocol)
{
int ret;
ID0set0();
ret = socket(domain, type, protocol);
LogPrintf(LogID0, "%d = socket(%d, %d, %d)\n", ret, domain, type, protocol);
ID0setuser();
return ret;
}
FILE *
ID0fopen(const char *path, const char *mode)
{
FILE *ret;
ID0set0();
ret = fopen(path, mode);
LogPrintf(LogID0, "%p = fopen(\"%s\", \"%s\")\n", ret, path, mode);
ID0setuser();
return ret;
}
int
ID0open(const char *path, int flags)
{
int ret;
ID0set0();
ret = open(path, flags);
LogPrintf(LogID0, "%d = open(\"%s\", %d)\n", ret, path, flags);
ID0setuser();
return ret;
}
int
ID0write(int fd, const void *data, size_t len)
{
int ret;
ID0set0();
ret = write(fd, data, len);
LogPrintf(LogID0, "%d = write(%d, data, %d)\n", ret, fd, len);
ID0setuser();
return ret;
}
int
ID0uu_lock(const char *basettyname)
{
int ret;
ID0set0();
ret = uu_lock(basettyname);
LogPrintf(LogID0, "%d = uu_lock(\"%s\")\n", ret, basettyname);
ID0setuser();
return ret;
}
int
ID0uu_unlock(const char *basettyname)
{
int ret;
ID0set0();
ret = uu_unlock(basettyname);
LogPrintf(LogID0, "%d = uu_unlock(\"%s\")\n", ret, basettyname);
ID0setuser();
return ret;
}

38
usr.sbin/ppp/id.h Normal file
View File

@ -0,0 +1,38 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: id.h,v 1.2 1997/12/21 12:11:05 brian Exp $
*/
extern void ID0init(void);
extern uid_t ID0realuid(void);
extern int ID0ioctl(int, unsigned long, void *);
extern int ID0unlink(const char *);
extern int ID0socket(int, int, int);
extern FILE *ID0fopen(const char *, const char *);
extern int ID0open(const char *, int);
extern int ID0write(int, const void *, size_t);
extern int ID0uu_lock(const char *);
extern int ID0uu_unlock(const char *);

537
usr.sbin/ppp/ip.c Normal file
View File

@ -0,0 +1,537 @@
/*
* PPP IP Protocol Interface
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: ip.c,v 1.37 1998/01/11 17:53:18 brian Exp $
*
* TODO:
* o Return ICMP message for filterd packet
* and optionaly record it into log.
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_tun.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#ifndef NOALIAS
#include <alias.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "hdlc.h"
#include "loadalias.h"
#include "vars.h"
#include "filter.h"
#include "os.h"
#include "ipcp.h"
#include "vjcomp.h"
#include "lcp.h"
#include "modem.h"
#include "tun.h"
#include "ip.h"
static struct pppTimer IdleTimer;
static void
IdleTimeout(void *v)
{
LogPrintf(LogPHASE, "Idle timer expired.\n");
reconnect(RECON_FALSE);
LcpClose();
}
/*
* Start Idle timer. If timeout is reached, we call LcpClose() to
* close LCP and link.
*/
void
StartIdleTimer()
{
static time_t IdleStarted;
if (!(mode & (MODE_DEDICATED | MODE_DDIAL))) {
StopTimer(&IdleTimer);
IdleTimer.func = IdleTimeout;
IdleTimer.load = VarIdleTimeout * SECTICKS;
IdleTimer.state = TIMER_STOPPED;
time(&IdleStarted);
IdleTimer.arg = (void *)&IdleStarted;
StartTimer(&IdleTimer);
}
}
void
UpdateIdleTimer()
{
if (OsLinkIsUp())
StartIdleTimer();
}
void
StopIdleTimer()
{
StopTimer(&IdleTimer);
}
int
RemainingIdleTime()
{
if (VarIdleTimeout == 0 || IdleTimer.state != TIMER_RUNNING ||
IdleTimer.arg == NULL)
return -1;
return VarIdleTimeout - (time(NULL) - *(time_t *)IdleTimer.arg);
}
/*
* If any IP layer traffic is detected, refresh IdleTimer.
*/
static void
RestartIdleTimer(void)
{
if (!(mode & (MODE_DEDICATED | MODE_DDIAL)) && ipKeepAlive) {
time((time_t *)IdleTimer.arg);
StartTimer(&IdleTimer);
}
}
static const u_short interactive_ports[32] = {
544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
};
#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p))
static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
static const char *Direction[] = {"INP", "OUT", "OUT", "IN/OUT"};
static struct filterent *Filters[] = {ifilters, ofilters, dfilters, afilters};
static int
PortMatch(int op, u_short pport, u_short rport)
{
switch (op) {
case OP_EQ:
return (pport == rport);
case OP_GT:
return (pport > rport);
case OP_LT:
return (pport < rport);
default:
return (0);
}
}
/*
* Check a packet against with defined filters
*/
static int
FilterCheck(struct ip * pip, int direction)
{
struct filterent *fp = Filters[direction];
int gotinfo, cproto, estab, n;
struct tcphdr *th;
struct udphdr *uh;
struct icmp *ih;
char *ptop;
u_short sport, dport;
if (fp->action) {
cproto = gotinfo = estab = 0;
sport = dport = 0;
for (n = 0; n < MAXFILTERS; n++) {
if (fp->action) {
/* permit fragments on in and out filter */
if ((direction == FL_IN || direction == FL_OUT) &&
(ntohs(pip->ip_off) & IP_OFFMASK) != 0) {
return (A_PERMIT);
}
LogPrintf(LogDEBUG, "rule = %d\n", n);
if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
(fp->saddr.s_addr & fp->smask.s_addr) &&
(pip->ip_dst.s_addr & fp->dmask.s_addr) ==
(fp->daddr.s_addr & fp->dmask.s_addr)) {
if (fp->proto) {
if (!gotinfo) {
ptop = (char *) pip + (pip->ip_hl << 2);
switch (pip->ip_p) {
case IPPROTO_ICMP:
cproto = P_ICMP;
ih = (struct icmp *) ptop;
sport = ih->icmp_type;
estab = 1;
break;
case IPPROTO_UDP:
cproto = P_UDP;
uh = (struct udphdr *) ptop;
sport = ntohs(uh->uh_sport);
dport = ntohs(uh->uh_dport);
estab = 1;
break;
case IPPROTO_TCP:
cproto = P_TCP;
th = (struct tcphdr *) ptop;
sport = ntohs(th->th_sport);
dport = ntohs(th->th_dport);
estab = (th->th_flags & TH_ACK);
if (estab == 0)
LogPrintf(LogDEBUG, "flag = %02x, sport = %d, dport = %d\n",
th->th_flags, sport, dport);
break;
default:
return (A_DENY);/* We'll block unknown type of packet */
}
gotinfo = 1;
LogPrintf(LogDEBUG, "dir = %d, proto = %d, srcop = %d,"
" dstop = %d, estab = %d\n", direction, cproto,
fp->opt.srcop, fp->opt.dstop, estab);
}
LogPrintf(LogDEBUG, "check0: rule = %d, proto = %d, sport = %d,"
" dport = %d\n", n, cproto, sport, dport);
LogPrintf(LogDEBUG, "check0: action = %d\n", fp->action);
if (cproto == fp->proto) {
if ((fp->opt.srcop == OP_NONE ||
PortMatch(fp->opt.srcop, sport, fp->opt.srcport))
&&
(fp->opt.dstop == OP_NONE ||
PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
&&
(fp->opt.estab == 0 || estab)) {
return (fp->action);
}
}
} else {
/* Address is mached. Make a decision. */
LogPrintf(LogDEBUG, "check1: action = %d\n", fp->action);
return (fp->action);
}
}
}
fp++;
}
return (A_DENY); /* No rule is mached. Deny this packet */
}
return (A_PERMIT); /* No rule is given. Permit this packet */
}
static void
IcmpError(struct ip * pip, int code)
{
#ifdef notdef
struct mbuf *bp;
if (pip->ip_p != IPPROTO_ICMP) {
bp = mballoc(cnt, MB_IPIN);
memcpy(MBUF_CTOP(bp), ptr, cnt);
SendPppFrame(bp);
RestartIdleTimer();
IpcpAddOutOctets(cnt);
}
#endif
}
/*
* For debugging aid.
*/
int
PacketCheck(char *cp, int nb, int direction)
{
struct ip *pip;
struct tcphdr *th;
struct udphdr *uh;
struct icmp *icmph;
char *ptop;
int mask, len, n;
int pri = PRI_NORMAL;
int logit, loglen;
static char logbuf[200];
logit = LogIsKept(LogTCPIP) && direction != FL_DIAL;
loglen = 0;
pip = (struct ip *) cp;
if (logit && loglen < sizeof logbuf) {
snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ",
Direction[direction]);
loglen += strlen(logbuf + loglen);
}
ptop = (cp + (pip->ip_hl << 2));
switch (pip->ip_p) {
case IPPROTO_ICMP:
if (logit && loglen < sizeof logbuf) {
icmph = (struct icmp *) ptop;
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
loglen += strlen(logbuf + loglen);
}
break;
case IPPROTO_UDP:
if (logit && loglen < sizeof logbuf) {
uh = (struct udphdr *) ptop;
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
loglen += strlen(logbuf + loglen);
}
break;
case IPPROTO_TCP:
th = (struct tcphdr *) ptop;
if (pip->ip_tos == IPTOS_LOWDELAY)
pri = PRI_FAST;
else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
pri = PRI_FAST;
}
if (logit && loglen < sizeof logbuf) {
len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
loglen += strlen(logbuf + loglen);
snprintf(logbuf + loglen, sizeof logbuf - loglen,
"%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
loglen += strlen(logbuf + loglen);
n = 0;
for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
if (th->th_flags & mask) {
snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
loglen += strlen(logbuf + loglen);
}
n++;
}
snprintf(logbuf + loglen, sizeof logbuf - loglen,
" seq:%x ack:%x (%d/%d)",
ntohl(th->th_seq), ntohl(th->th_ack), len, nb);
loglen += strlen(logbuf + loglen);
if ((th->th_flags & TH_SYN) && nb > 40) {
u_short *sp;
ptop += 20;
sp = (u_short *) ptop;
if (ntohs(sp[0]) == 0x0204) {
snprintf(logbuf + loglen, sizeof logbuf - loglen,
" MSS = %d", ntohs(sp[1]));
loglen += strlen(logbuf + loglen);
}
}
}
break;
}
if ((FilterCheck(pip, direction) & A_DENY)) {
if (logit)
LogPrintf(LogTCPIP, "%s - BLOCKED\n", logbuf);
if (direction == 0)
IcmpError(pip, pri);
return (-1);
} else {
if (FilterCheck(pip, FL_KEEP) & A_DENY) { /* Check Keep Alive filter */
if (logit)
LogPrintf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
ipKeepAlive = 0;
} else {
if (logit)
LogPrintf(LogTCPIP, "%s\n", logbuf);
ipKeepAlive = 1;
}
return (pri);
}
}
void
IpInput(struct mbuf * bp)
{ /* IN: Pointer to IP pakcet */
u_char *cp;
struct mbuf *wp;
int nb, nw;
struct tun_data tun;
tun_fill_header(tun, AF_INET);
cp = tun.data;
nb = 0;
for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */
if (sizeof tun.data - (cp - tun.data) < wp->cnt) {
LogPrintf(LogERROR, "IpInput: Packet too large (%d) - dropped\n",
plength(bp));
pfree(bp);
return;
}
memcpy(cp, MBUF_CTOP(wp), wp->cnt);
cp += wp->cnt;
nb += wp->cnt;
}
#ifndef NOALIAS
if (mode & MODE_ALIAS) {
struct tun_data *frag;
int iresult;
char *fptr;
iresult = VarPacketAliasIn(tun.data, sizeof tun.data);
nb = ntohs(((struct ip *) tun.data)->ip_len);
if (nb > MAX_MRU) {
LogPrintf(LogERROR, "IpInput: Problem with IP header length\n");
pfree(bp);
return;
}
if (iresult == PKT_ALIAS_OK
|| iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
if (PacketCheck(tun.data, nb, FL_IN) < 0) {
pfree(bp);
return;
}
IpcpAddInOctets(nb);
nb = ntohs(((struct ip *) tun.data)->ip_len);
nb += sizeof tun - sizeof tun.data;
nw = write(tun_out, &tun, nb);
if (nw != nb)
if (nw == -1)
LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb,
strerror(errno));
else
LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
while ((fptr = VarPacketAliasGetFragment(tun.data)) != NULL) {
VarPacketAliasFragmentIn(tun.data, fptr);
nb = ntohs(((struct ip *) fptr)->ip_len);
frag = (struct tun_data *)
((char *)fptr - sizeof tun + sizeof tun.data);
nb += sizeof tun - sizeof tun.data;
nw = write(tun_out, frag, nb);
if (nw != nb)
if (nw == -1)
LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb,
strerror(errno));
else
LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
free(frag);
}
}
} else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) {
nb = ntohs(((struct ip *) tun.data)->ip_len);
nb += sizeof tun - sizeof tun.data;
frag = (struct tun_data *)malloc(nb);
if (frag == NULL)
LogPrintf(LogALERT, "IpInput: Cannot allocate memory for fragment\n");
else {
tun_fill_header(*frag, AF_INET);
memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data);
VarPacketAliasSaveFragment(frag->data);
}
}
} else
#endif /* #ifndef NOALIAS */
{ /* no aliasing */
if (PacketCheck(tun.data, nb, FL_IN) < 0) {
pfree(bp);
return;
}
IpcpAddInOctets(nb);
nb += sizeof tun - sizeof tun.data;
nw = write(tun_out, &tun, nb);
if (nw != nb)
if (nw == -1)
LogPrintf(LogERROR, "IpInput: wrote %d, got %s\n", nb, strerror(errno));
else
LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
}
pfree(bp);
RestartIdleTimer();
}
static struct mqueue IpOutputQueues[PRI_FAST + 1];
void
IpEnqueue(int pri, char *ptr, int count)
{
struct mbuf *bp;
bp = mballoc(count, MB_IPQ);
memcpy(MBUF_CTOP(bp), ptr, count);
Enqueue(&IpOutputQueues[pri], bp);
}
#if 0
int
IsIpEnqueued()
{
struct mqueue *queue;
int exist = 0;
for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) {
if (queue->qlen > 0) {
exist = 1;
break;
}
}
return (exist);
}
#endif
void
IpStartOutput()
{
struct mqueue *queue;
struct mbuf *bp;
int cnt;
if (IpcpFsm.state != ST_OPENED)
return;
for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) {
if (queue->top) {
bp = Dequeue(queue);
if (bp) {
cnt = plength(bp);
SendPppFrame(bp);
RestartIdleTimer();
IpcpAddOutOctets(cnt);
break;
}
}
}
}

31
usr.sbin/ppp/ip.h Normal file
View File

@ -0,0 +1,31 @@
/*
* User Process PPP
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: ip.h,v 1.7 1997/10/26 12:42:11 brian Exp $
*
*/
extern void IpStartOutput(void);
extern int PacketCheck(char *, int, int);
extern void IpEnqueue(int, char *, int);
extern void IpInput(struct mbuf *);
extern void StartIdleTimer(void);
extern void StopIdleTimer(void);
extern void UpdateIdleTimer(void);
extern int RemainingIdleTime(void);

710
usr.sbin/ppp/ipcp.c Normal file
View File

@ -0,0 +1,710 @@
/*
* PPP IP Control Protocol (IPCP) Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: ipcp.c,v 1.49 1998/01/20 22:47:38 brian Exp $
*
* TODO:
* o More RFC1772 backwoard compatibility
*/
#include <sys/param.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "lcpproto.h"
#include "lcp.h"
#include "iplist.h"
#include "ipcp.h"
#include "slcompress.h"
#include "os.h"
#include "phase.h"
#include "loadalias.h"
#include "vars.h"
#include "vjcomp.h"
#include "ip.h"
#include "throughput.h"
#include "route.h"
#include "filter.h"
#ifndef NOMSEXT
struct in_addr ns_entries[2];
struct in_addr nbns_entries[2];
#endif
struct ipcpstate IpcpInfo;
struct in_range DefMyAddress;
struct in_range DefHisAddress;
struct iplist DefHisChoice;
struct in_addr TriggerAddress;
int HaveTriggerAddress;
static void IpcpSendConfigReq(struct fsm *);
static void IpcpSendTerminateAck(struct fsm *);
static void IpcpSendTerminateReq(struct fsm *);
static void IpcpDecodeConfig(u_char *, int, int);
static void IpcpLayerStart(struct fsm *);
static void IpcpLayerFinish(struct fsm *);
static void IpcpLayerUp(struct fsm *);
static void IpcpLayerDown(struct fsm *);
static void IpcpInitRestartCounter(struct fsm *);
struct fsm IpcpFsm = {
"IPCP",
PROTO_IPCP,
IPCP_MAXCODE,
0,
ST_INITIAL,
0, 0, 0,
{0, 0, 0, NULL, NULL, NULL}, /* FSM timer */
{0, 0, 0, NULL, NULL, NULL}, /* Open timer */
{0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */
LogIPCP,
IpcpLayerUp,
IpcpLayerDown,
IpcpLayerStart,
IpcpLayerFinish,
IpcpInitRestartCounter,
IpcpSendConfigReq,
IpcpSendTerminateReq,
IpcpSendTerminateAck,
IpcpDecodeConfig,
};
static const char *cftypes[] = {
/* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
"???",
"IPADDRS", /* 1: IP-Addresses */ /* deprecated */
"COMPPROTO", /* 2: IP-Compression-Protocol */
"IPADDR", /* 3: IP-Address */
};
#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
static const char *cftypes128[] = {
/* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
"???",
"PRIDNS", /* 129: Primary DNS Server Address */
"PRINBNS", /* 130: Primary NBNS Server Address */
"SECDNS", /* 131: Secondary DNS Server Address */
"SECNBNS", /* 132: Secondary NBNS Server Address */
};
#define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0])
static struct pppThroughput throughput;
void
IpcpAddInOctets(int n)
{
throughput_addin(&throughput, n);
}
void
IpcpAddOutOctets(int n)
{
throughput_addout(&throughput, n);
}
int
ReportIpcpStatus(struct cmdargs const *arg)
{
struct fsm *fp = &IpcpFsm;
if (!VarTerm)
return 1;
fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
if (IpcpFsm.state == ST_OPENED) {
fprintf(VarTerm, " his side: %s, %s\n",
inet_ntoa(IpcpInfo.his_ipaddr), vj2asc(IpcpInfo.his_compproto));
fprintf(VarTerm, " my side: %s, %s\n",
inet_ntoa(IpcpInfo.want_ipaddr), vj2asc(IpcpInfo.want_compproto));
}
fprintf(VarTerm, "Defaults:\n");
fprintf(VarTerm, " My Address: %s/%d\n",
inet_ntoa(DefMyAddress.ipaddr), DefMyAddress.width);
if (iplist_isvalid(&DefHisChoice))
fprintf(VarTerm, " His Address: %s\n", DefHisChoice.src);
else
fprintf(VarTerm, " His Address: %s/%d\n",
inet_ntoa(DefHisAddress.ipaddr), DefHisAddress.width);
if (HaveTriggerAddress)
fprintf(VarTerm, " Negotiation(trigger): %s\n", inet_ntoa(TriggerAddress));
else
fprintf(VarTerm, " Negotiation(trigger): MYADDR\n");
fprintf(VarTerm, "\n");
throughput_disp(&throughput, VarTerm);
return 0;
}
void
IpcpDefAddress()
{
struct hostent *hp;
char name[200];
memset(&DefMyAddress, '\0', sizeof DefMyAddress);
memset(&DefHisAddress, '\0', sizeof DefHisAddress);
TriggerAddress.s_addr = 0;
HaveTriggerAddress = 0;
if (gethostname(name, sizeof name) == 0) {
hp = gethostbyname(name);
if (hp && hp->h_addrtype == AF_INET) {
memcpy(&DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length);
}
}
}
static int VJInitSlots = MAX_STATES;
static int VJInitComp = 1;
int
SetInitVJ(struct cmdargs const *args)
{
if (args->argc != 2)
return -1;
if (!strcasecmp(args->argv[0], "slots")) {
int slots;
slots = atoi(args->argv[1]);
if (slots < 4 || slots > 16)
return 1;
VJInitSlots = slots;
return 0;
} else if (!strcasecmp(args->argv[0], "slotcomp")) {
if (!strcasecmp(args->argv[1], "on"))
VJInitComp = 1;
else if (!strcasecmp(args->argv[1], "off"))
VJInitComp = 0;
else
return 2;
return 0;
}
return -1;
}
int
ShowInitVJ(struct cmdargs const *args)
{
if (VarTerm) {
fprintf(VarTerm, "Initial slots: %d\n", VJInitSlots);
fprintf(VarTerm, "Initial compression: %s\n", VJInitComp ? "on" : "off");
}
return 0;
}
void
IpcpInit()
{
if (iplist_isvalid(&DefHisChoice))
iplist_setrandpos(&DefHisChoice);
FsmInit(&IpcpFsm);
memset(&IpcpInfo, '\0', sizeof IpcpInfo);
if ((mode & MODE_DEDICATED) && !GetLabel()) {
IpcpInfo.want_ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr = 0;
} else {
IpcpInfo.want_ipaddr.s_addr = DefMyAddress.ipaddr.s_addr;
IpcpInfo.his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
}
/*
* Some implementations of PPP require that we send a
* *special* value as our address, even though the rfc specifies
* full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
*/
if (HaveTriggerAddress) {
IpcpInfo.want_ipaddr.s_addr = TriggerAddress.s_addr;
LogPrintf(LogIPCP, "Using trigger address %s\n", inet_ntoa(TriggerAddress));
}
if (Enabled(ConfVjcomp))
IpcpInfo.want_compproto = (PROTO_VJCOMP << 16) | ((VJInitSlots - 1) << 8) |
VJInitComp;
else
IpcpInfo.want_compproto = 0;
IpcpInfo.heis1172 = 0;
IpcpFsm.maxconfig = 10;
throughput_init(&throughput);
}
static void
IpcpInitRestartCounter(struct fsm * fp)
{
fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
fp->restart = 5;
}
static void
IpcpSendConfigReq(struct fsm * fp)
{
u_char *cp;
struct lcp_opt o;
cp = ReqBuff;
LogPrintf(LogIPCP, "IpcpSendConfigReq\n");
if (!DEV_IS_SYNC || !REJECTED(&IpcpInfo, TY_IPADDR)) {
o.id = TY_IPADDR;
o.len = 6;
*(u_long *)o.data = IpcpInfo.want_ipaddr.s_addr;
cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id],
inet_ntoa(IpcpInfo.want_ipaddr));
}
if (IpcpInfo.want_compproto && !REJECTED(&IpcpInfo, TY_COMPPROTO)) {
const char *args;
o.id = TY_COMPPROTO;
if (IpcpInfo.heis1172) {
o.len = 4;
*(u_short *)o.data = htons(PROTO_VJCOMP);
args = "";
} else {
o.len = 6;
*(u_long *)o.data = htonl(IpcpInfo.want_compproto);
args = vj2asc(IpcpInfo.want_compproto);
}
cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], args);
}
FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
}
static void
IpcpSendTerminateReq(struct fsm * fp)
{
/* XXX: No code yet */
}
static void
IpcpSendTerminateAck(struct fsm * fp)
{
LogPrintf(LogIPCP, "IpcpSendTerminateAck\n");
FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
}
static void
IpcpLayerStart(struct fsm * fp)
{
LogPrintf(LogIPCP, "IpcpLayerStart.\n");
}
static void
IpcpLayerFinish(struct fsm * fp)
{
LogPrintf(LogIPCP, "IpcpLayerFinish.\n");
reconnect(RECON_FALSE);
LcpClose();
NewPhase(PHASE_TERMINATE);
}
static void
IpcpLayerDown(struct fsm * fp)
{
LogPrintf(LogIPCP, "IpcpLayerDown.\n");
throughput_stop(&throughput);
throughput_log(&throughput, LogIPCP, NULL);
}
/*
* Called when IPCP has reached to OPEN state
*/
static void
IpcpLayerUp(struct fsm * fp)
{
char tbuff[100];
Prompt();
LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state);
snprintf(tbuff, sizeof tbuff, "myaddr = %s ",
inet_ntoa(IpcpInfo.want_ipaddr));
if (IpcpInfo.his_compproto >> 16 == PROTO_VJCOMP)
VjInit((IpcpInfo.his_compproto >> 8) & 255);
LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n",
tbuff, inet_ntoa(IpcpInfo.his_ipaddr));
if (OsSetIpaddress(IpcpInfo.want_ipaddr, IpcpInfo.his_ipaddr) < 0) {
if (VarTerm)
LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n");
return;
}
#ifndef NOALIAS
if (mode & MODE_ALIAS)
VarPacketAliasSetAddress(IpcpInfo.want_ipaddr);
#endif
OsLinkup();
throughput_start(&throughput);
StartIdleTimer();
}
void
IpcpUp()
{
FsmUp(&IpcpFsm);
LogPrintf(LogIPCP, "IPCP Up event!!\n");
}
void
IpcpOpen()
{
FsmOpen(&IpcpFsm);
}
static int
AcceptableAddr(struct in_range * prange, struct in_addr ipaddr)
{
LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr));
LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr));
LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr));
LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange->
mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr));
return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
(ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
}
static void
IpcpDecodeConfig(u_char * cp, int plen, int mode_type)
{
int type, length;
u_long *lp, compproto;
struct compreq *pcomp;
struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req;
char tbuff[100];
char tbuff2[100];
ackp = AckBuff;
nakp = NakBuff;
rejp = RejBuff;
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
if (type < NCFTYPES)
snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length);
else if (type > 128 && type < 128 + NCFTYPES128)
snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length);
else
snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length);
switch (type) {
case TY_IPADDR: /* RFC1332 */
lp = (u_long *) (cp + 2);
ipaddr.s_addr = *lp;
LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
switch (mode_type) {
case MODE_REQ:
if (iplist_isvalid(&DefHisChoice)) {
if (ipaddr.s_addr == INADDR_ANY ||
iplist_ip2pos(&DefHisChoice, ipaddr) < 0 ||
OsTrySetIpaddress(DefMyAddress.ipaddr, ipaddr) != 0) {
LogPrintf(LogIPCP, "%s: Address invalid or already in use\n",
inet_ntoa(ipaddr));
IpcpInfo.his_ipaddr = ChooseHisAddr(DefMyAddress.ipaddr);
if (IpcpInfo.his_ipaddr.s_addr == INADDR_ANY) {
memcpy(rejp, cp, length);
rejp += length;
} else {
memcpy(nakp, cp, 2);
memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length - 2);
nakp += length;
}
break;
}
} else if (!AcceptableAddr(&DefHisAddress, ipaddr)) {
/*
* If destination address is not acceptable, insist to use what we
* want to use.
*/
memcpy(nakp, cp, 2);
memcpy(nakp+2, &IpcpInfo.his_ipaddr.s_addr, length - 2);
nakp += length;
break;
}
IpcpInfo.his_ipaddr = ipaddr;
memcpy(ackp, cp, length);
ackp += length;
break;
case MODE_NAK:
if (AcceptableAddr(&DefMyAddress, ipaddr)) {
/* Use address suggested by peer */
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
inet_ntoa(IpcpInfo.want_ipaddr));
LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
IpcpInfo.want_ipaddr = ipaddr;
} else {
LogPrintf(LogIPCP, "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
FsmClose(&IpcpFsm);
}
break;
case MODE_REJ:
IpcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_COMPPROTO:
lp = (u_long *) (cp + 2);
compproto = htonl(*lp);
LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
switch (mode_type) {
case MODE_REQ:
if (!Acceptable(ConfVjcomp)) {
memcpy(rejp, cp, length);
rejp += length;
} else {
pcomp = (struct compreq *) (cp + 2);
switch (length) {
case 4: /* RFC1172 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
IpcpInfo.heis1172 = 1;
IpcpInfo.his_compproto = compproto;
memcpy(ackp, cp, length);
ackp += length;
} else {
memcpy(nakp, cp, 2);
pcomp->proto = htons(PROTO_VJCOMP);
memcpy(nakp+2, &pcomp, 2);
nakp += length;
}
break;
case 6: /* RFC1332 */
if (ntohs(pcomp->proto) == PROTO_VJCOMP
&& pcomp->slots < MAX_STATES && pcomp->slots > 2) {
IpcpInfo.his_compproto = compproto;
IpcpInfo.heis1172 = 0;
memcpy(ackp, cp, length);
ackp += length;
} else {
memcpy(nakp, cp, 2);
pcomp->proto = htons(PROTO_VJCOMP);
pcomp->slots = MAX_STATES - 1;
pcomp->compcid = 0;
memcpy(nakp+2, &pcomp, sizeof pcomp);
nakp += length;
}
break;
default:
memcpy(rejp, cp, length);
rejp += length;
break;
}
}
break;
case MODE_NAK:
LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
tbuff, IpcpInfo.want_compproto, compproto);
IpcpInfo.want_compproto = compproto;
break;
case MODE_REJ:
IpcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_IPADDRS: /* RFC1172 */
lp = (u_long *) (cp + 2);
ipaddr.s_addr = *lp;
lp = (u_long *) (cp + 6);
dstipaddr.s_addr = *lp;
snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
switch (mode_type) {
case MODE_REQ:
IpcpInfo.his_ipaddr = ipaddr;
IpcpInfo.want_ipaddr = dstipaddr;
memcpy(ackp, cp, length);
ackp += length;
break;
case MODE_NAK:
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff,
inet_ntoa(IpcpInfo.want_ipaddr));
LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
IpcpInfo.want_ipaddr = ipaddr;
IpcpInfo.his_ipaddr = dstipaddr;
break;
case MODE_REJ:
IpcpInfo.his_reject |= (1 << type);
break;
}
break;
/*
* MS extensions for MS's PPP
*/
#ifndef NOMSEXT
case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */
case TY_SECONDARY_DNS:
if (!Enabled(ConfMSExt)) {
LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n");
IpcpInfo.my_reject |= (1 << type);
memcpy(rejp, cp, length);
rejp += length;
break;
}
switch (mode_type) {
case MODE_REQ:
lp = (u_long *) (cp + 2);
dnsstuff.s_addr = *lp;
ms_info_req.s_addr = ns_entries[((type - TY_PRIMARY_DNS) ? 1 : 0)].s_addr;
if (dnsstuff.s_addr != ms_info_req.s_addr) {
/*
* So the client has got the DNS stuff wrong (first request) so
* we'll tell 'em how it is
*/
memcpy(nakp, cp, 2); /* copy first two (type/length) */
LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n",
type,
inet_ntoa(dnsstuff),
inet_ntoa(ms_info_req));
memcpy(nakp+2, &ms_info_req, length);
nakp += length;
break;
}
/*
* Otherwise they have it right (this time) so we send a ack packet
* back confirming it... end of story
*/
LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n",
type,
inet_ntoa(ms_info_req));
memcpy(ackp, cp, length);
ackp += length;
break;
case MODE_NAK: /* what does this mean?? */
LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type);
break;
case MODE_REJ: /* confused?? me to :) */
LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type);
break;
}
break;
case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */
case TY_SECONDARY_NBNS:
if (!Enabled(ConfMSExt)) {
LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n");
IpcpInfo.my_reject |= (1 << type);
memcpy(rejp, cp, length);
rejp += length;
break;
}
switch (mode_type) {
case MODE_REQ:
lp = (u_long *) (cp + 2);
dnsstuff.s_addr = *lp;
ms_info_req.s_addr = nbns_entries[((type - TY_PRIMARY_NBNS) ? 1 : 0)].s_addr;
if (dnsstuff.s_addr != ms_info_req.s_addr) {
memcpy(nakp, cp, 2);
memcpy(nakp+2, &ms_info_req.s_addr, length);
LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n",
type,
inet_ntoa(dnsstuff),
inet_ntoa(ms_info_req));
nakp += length;
break;
}
LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n",
type,
inet_ntoa(ms_info_req));
memcpy(ackp, cp, length);
ackp += length;
break;
case MODE_NAK:
LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
break;
case MODE_REJ:
LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
break;
}
break;
#endif
default:
IpcpInfo.my_reject |= (1 << type);
memcpy(rejp, cp, length);
rejp += length;
break;
}
plen -= length;
cp += length;
}
}
void
IpcpInput(struct mbuf * bp)
{
FsmInput(&IpcpFsm, bp);
}
int
UseHisaddr(const char *hisaddr, int setaddr)
{
memset(&DefHisAddress, '\0', sizeof DefHisAddress);
iplist_reset(&DefHisChoice);
if (strpbrk(hisaddr, ",-")) {
iplist_setsrc(&DefHisChoice, hisaddr);
if (iplist_isvalid(&DefHisChoice)) {
iplist_setrandpos(&DefHisChoice);
IpcpInfo.his_ipaddr = ChooseHisAddr(IpcpInfo.want_ipaddr);
if (IpcpInfo.his_ipaddr.s_addr == INADDR_ANY) {
LogPrintf(LogWARN, "%s: None available !\n", DefHisChoice.src);
return(0);
}
DefHisAddress.ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr;
DefHisAddress.mask.s_addr = 0xffffffff;
DefHisAddress.width = 32;
} else {
LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr);
return 0;
}
} else if (ParseAddr(1, &hisaddr, &DefHisAddress.ipaddr,
&DefHisAddress.mask, &DefHisAddress.width) != 0) {
IpcpInfo.his_ipaddr.s_addr = DefHisAddress.ipaddr.s_addr;
if (setaddr && OsSetIpaddress
(DefMyAddress.ipaddr, DefHisAddress.ipaddr) < 0) {
DefMyAddress.ipaddr.s_addr = DefHisAddress.ipaddr.s_addr = 0L;
return 0;
}
} else
return 0;
return 1;
}

83
usr.sbin/ppp/ipcp.h Normal file
View File

@ -0,0 +1,83 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: ipcp.h,v 1.17 1998/01/11 17:50:33 brian Exp $
*
* TODO:
*/
#define IPCP_MAXCODE CODE_CODEREJ
#define TY_IPADDRS 1
#define TY_COMPPROTO 2
#define TY_IPADDR 3
/* MS PPP NameServer and NetBIOS NameServer stuff */
#ifndef NOMSEXT
#define TY_PRIMARY_DNS 129
#define TY_PRIMARY_NBNS 130
#define TY_SECONDARY_DNS 131
#define TY_SECONDARY_NBNS 132
extern struct in_addr ns_entries[2];
extern struct in_addr nbns_entries[2];
#endif
struct ipcpstate {
struct in_addr his_ipaddr; /* IP address he is willing to use */
u_int32_t his_compproto;
struct in_addr want_ipaddr; /* IP address I'm willing to use */
u_int32_t want_compproto;
u_int32_t his_reject; /* Request codes rejected by peer */
u_int32_t my_reject; /* Request codes I have rejected */
int heis1172; /* True if he is speaking rfc1172 */
};
struct compreq {
u_short proto;
u_char slots;
u_char compcid;
};
struct in_range {
struct in_addr ipaddr;
struct in_addr mask;
int width;
};
extern struct ipcpstate IpcpInfo;
extern struct in_range DefMyAddress;
extern struct in_range DefHisAddress;
extern struct iplist DefHisChoice;
extern struct in_addr TriggerAddress;
extern int HaveTriggerAddress;
extern struct fsm IpcpFsm;
extern void IpcpInit(void);
extern void IpcpDefAddress(void);
extern void IpcpUp(void);
extern void IpcpOpen(void);
extern int ReportIpcpStatus(struct cmdargs const *);
extern void IpcpInput(struct mbuf *);
extern void IpcpAddInOctets(int);
extern void IpcpAddOutOctets(int);
extern int UseHisaddr(const char *, int);
extern int SetInitVJ(struct cmdargs const *);
extern int ShowInitVJ(struct cmdargs const *);

224
usr.sbin/ppp/iplist.c Normal file
View File

@ -0,0 +1,224 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: iplist.c,v 1.3 1997/12/23 22:38:54 brian Exp $
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "iplist.h"
static int
do_inet_aton(const char *start, const char *end, struct in_addr *ip)
{
static char ipstr[16];
if (end - start > 15) {
LogPrintf(LogWARN, "%.*s: Invalid IP address\n", end-start, start);
return 0;
}
strncpy(ipstr, start, end-start);
ipstr[end-start] = '\0';
return inet_aton(ipstr, ip);
}
static void
iplist_first(struct iplist *list)
{
list->cur.pos = -1;
}
static int
iplist_setrange(struct iplist *list, char *range)
{
char *ptr, *to;
if ((ptr = strpbrk(range, ",-")) == NULL) {
if (!inet_aton(range, &list->cur.ip))
return 0;
list->cur.lstart = ntohl(list->cur.ip.s_addr);
list->cur.nItems = 1;
} else {
if (!do_inet_aton(range, ptr, &list->cur.ip))
return 0;
if (*ptr == ',') {
list->cur.lstart = ntohl(list->cur.ip.s_addr);
list->cur.nItems = 1;
} else {
struct in_addr endip;
to = ptr+1;
if ((ptr = strpbrk(to, ",-")) == NULL)
ptr = to + strlen(to);
if (*to == '-')
return 0;
if (!do_inet_aton(to, ptr, &endip))
return 0;
list->cur.lstart = ntohl(list->cur.ip.s_addr);
list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1;
if (list->cur.nItems < 1)
return 0;
}
}
list->cur.srcitem = 0;
list->cur.srcptr = range;
return 1;
}
static int
iplist_nextrange(struct iplist *list)
{
char *ptr, *to, *end;
ptr = list->cur.srcptr;
if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL)
ptr++;
else
ptr = list->src;
while (*ptr != '\0' && !iplist_setrange(list, ptr)) {
if ((end = strchr(ptr, ',')) == NULL)
end = ptr + strlen(ptr);
if (end == ptr)
return 0;
LogPrintf(LogWARN, "%.*s: Invalid IP range (skipping)\n", end - ptr, ptr);
to = ptr;
do
*to = *end++;
while (*to++ != '\0');
if (*ptr == '\0')
ptr = list->src;
}
return 1;
}
struct in_addr
iplist_next(struct iplist *list)
{
if (list->cur.pos == -1) {
list->cur.srcptr = NULL;
if (!iplist_nextrange(list)) {
list->cur.ip.s_addr = INADDR_ANY;
return list->cur.ip;
}
} else if (++list->cur.srcitem == list->cur.nItems) {
if (!iplist_nextrange(list)) {
list->cur.ip.s_addr = INADDR_ANY;
list->cur.pos = -1;
return list->cur.ip;
}
} else
list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
list->cur.pos++;
return list->cur.ip;
}
int
iplist_setsrc(struct iplist *list, const char *src)
{
strncpy(list->src, src, sizeof list->src - 1);
list->src[sizeof list->src - 1] = '\0';
list->cur.srcptr = list->src;
do {
if (iplist_nextrange(list))
list->nItems += list->cur.nItems;
else
return 0;
} while (list->cur.srcptr != list->src);
return 1;
}
void
iplist_reset(struct iplist *list)
{
list->src[0] = '\0';
list->nItems = 0;
list->cur.pos = -1;
}
struct in_addr
iplist_setcurpos(struct iplist *list, int pos)
{
if (pos < 0 || pos >= list->nItems) {
list->cur.pos = -1;
list->cur.ip.s_addr = INADDR_ANY;
return list->cur.ip;
}
list->cur.srcptr = NULL;
list->cur.pos = 0;
while (1) {
iplist_nextrange(list);
if (pos < list->cur.nItems) {
if (pos) {
list->cur.srcitem = pos;
list->cur.pos += pos;
list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
}
break;
}
pos -= list->cur.nItems;
list->cur.pos += list->cur.nItems;
}
return list->cur.ip;
}
struct in_addr
iplist_setrandpos(struct iplist *list)
{
randinit();
return iplist_setcurpos(list, random() % list->nItems);
}
int
iplist_ip2pos(struct iplist *list, struct in_addr ip)
{
struct iplist_cur cur;
int f, result;
result = -1;
memcpy(&cur, &list->cur, sizeof cur);
for (iplist_first(list), f = 0; f < list->nItems; f++)
if (iplist_next(list).s_addr == ip.s_addr) {
result = list->cur.pos;
break;
}
memcpy(&list->cur, &cur, sizeof list->cur);
return result;
}

48
usr.sbin/ppp/iplist.h Normal file
View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
struct iplist {
struct iplist_cur {
struct in_addr ip;
int pos;
char *srcptr;
int srcitem;
u_long lstart, nItems;
} cur;
int nItems;
char src[LINE_LEN];
};
extern int iplist_setsrc(struct iplist *, const char *);
extern void iplist_reset(struct iplist *);
extern struct in_addr iplist_setcurpos(struct iplist *, int);
extern struct in_addr iplist_setrandpos(struct iplist *);
extern int iplist_ip2pos(struct iplist *, struct in_addr);
extern struct in_addr iplist_next(struct iplist *);
#define iplist_isvalid(x) ((x)->src[0] != '\0')

835
usr.sbin/ppp/lcp.c Normal file
View File

@ -0,0 +1,835 @@
/*
* PPP Link Control Protocol (LCP) Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: lcp.c,v 1.54 1998/01/20 22:47:40 brian Exp $
*
* TODO:
* o Validate magic number received from peer.
* o Limit data field length by MRU
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_tun.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
#include "lcpproto.h"
#include "os.h"
#include "hdlc.h"
#include "ccp.h"
#include "lqr.h"
#include "phase.h"
#include "loadalias.h"
#include "vars.h"
#include "auth.h"
#include "pap.h"
#include "chap.h"
#include "async.h"
#include "main.h"
#include "ip.h"
#include "modem.h"
#include "tun.h"
/* for received LQRs */
struct lqrreq {
u_char type;
u_char length;
u_short proto; /* Quality protocol */
u_long period; /* Reporting interval */
};
struct lcpstate LcpInfo;
static void LcpSendConfigReq(struct fsm *);
static void LcpSendTerminateReq(struct fsm *);
static void LcpSendTerminateAck(struct fsm *);
static void LcpDecodeConfig(u_char *, int, int);
static void LcpInitRestartCounter(struct fsm *);
static void LcpLayerUp(struct fsm *);
static void LcpLayerDown(struct fsm *);
static void LcpLayerStart(struct fsm *);
static void LcpLayerFinish(struct fsm *);
static const char *cftypes[] = {
/* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
"???",
"MRU", /* 1: Maximum-Receive-Unit */
"ACCMAP", /* 2: Async-Control-Character-Map */
"AUTHPROTO", /* 3: Authentication-Protocol */
"QUALPROTO", /* 4: Quality-Protocol */
"MAGICNUM", /* 5: Magic-Number */
"RESERVED", /* 6: RESERVED */
"PROTOCOMP", /* 7: Protocol-Field-Compression */
"ACFCOMP", /* 8: Address-and-Control-Field-Compression */
"FCSALT", /* 9: FCS-Alternatives */
"SDP", /* 10: Self-Describing-Pad */
"NUMMODE", /* 11: Numbered-Mode */
"MULTIPROC", /* 12: Multi-Link-Procedure */
"CALLBACK", /* 13: Callback */
"CONTIME", /* 14: Connect-Time */
"COMPFRAME", /* 15: Compound-Frames */
"NDE", /* 16: Nominal-Data-Encapsulation */
"MULTIMRRU", /* 17: Multilink-MRRU */
"MULTISSNH", /* 18: Multilink-Short-Sequence-Number-Header */
"MULTIED", /* 19: Multilink-Endpoint-Descriminator */
"PROPRIETRY", /* 20: Proprietary */
"DCEID", /* 21: DCE-Identifier */
"MULTIPP", /* 22: Multi-Link-Plus-Procedure */
"LDBACP", /* 23: Link Discriminator for BACP */
};
#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
struct fsm LcpFsm = {
"LCP", /* Name of protocol */
PROTO_LCP, /* Protocol Number */
LCP_MAXCODE,
1, /* Open mode delay */
ST_INITIAL, /* State of machine */
0, 0, 0,
{0, 0, 0, NULL, NULL, NULL}, /* FSM timer */
{0, 0, 0, NULL, NULL, NULL}, /* Open timer */
{0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */
LogLCP,
LcpLayerUp,
LcpLayerDown,
LcpLayerStart,
LcpLayerFinish,
LcpInitRestartCounter,
LcpSendConfigReq,
LcpSendTerminateReq,
LcpSendTerminateAck,
LcpDecodeConfig,
};
static struct pppTimer LcpReportTimer;
static int LcpFailedMagic;
static void
LcpReportTime(void *data)
{
if (LogIsKept(LogDEBUG)) {
time_t t;
time(&t);
LogPrintf(LogDEBUG, "LcpReportTime: %s\n", ctime(&t));
}
StopTimer(&LcpReportTimer);
LcpReportTimer.state = TIMER_STOPPED;
StartTimer(&LcpReportTimer);
HdlcErrorCheck();
}
int
ReportLcpStatus(struct cmdargs const *arg)
{
struct lcpstate *lcp = &LcpInfo;
struct fsm *fp = &LcpFsm;
if (!VarTerm)
return 1;
fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
fprintf(VarTerm,
" his side: MRU %d, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d,\n"
" MAGIC %08lx, REJECT %04x\n",
lcp->his_mru, (u_long)lcp->his_accmap, lcp->his_protocomp,
lcp->his_acfcomp, (u_long)lcp->his_magic, lcp->his_reject);
fprintf(VarTerm,
" my side: MRU %d, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d,\n"
" MAGIC %08lx, REJECT %04x\n",
lcp->want_mru, (u_long)lcp->want_accmap, lcp->want_protocomp,
lcp->want_acfcomp, (u_long)lcp->want_magic, lcp->my_reject);
fprintf(VarTerm, "\nDefaults: MRU = %d, ACCMAP = %08lx\t",
VarMRU, (u_long)VarAccmap);
fprintf(VarTerm, "Open Mode: %s",
(VarOpenMode == OPEN_PASSIVE) ? "passive" : "active");
if (VarOpenMode > 0)
fprintf(VarTerm, " (delay %d)", VarOpenMode);
fputc('\n', VarTerm);
return 0;
}
/*
* Generate random number which will be used as magic number.
*/
static u_int32_t
GenerateMagic(void)
{
randinit();
return (random());
}
void
LcpInit()
{
struct lcpstate *lcp = &LcpInfo;
FsmInit(&LcpFsm);
HdlcInit();
memset(lcp, '\0', sizeof(struct lcpstate));
lcp->want_mru = VarMRU;
lcp->his_mru = DEF_MRU;
lcp->his_accmap = 0xffffffff;
lcp->want_accmap = VarAccmap;
lcp->want_magic = GenerateMagic();
lcp->want_auth = lcp->his_auth = 0;
if (Enabled(ConfChap))
lcp->want_auth = PROTO_CHAP;
else if (Enabled(ConfPap))
lcp->want_auth = PROTO_PAP;
if (Enabled(ConfLqr))
lcp->want_lqrperiod = VarLqrTimeout * 100;
if (Enabled(ConfAcfcomp))
lcp->want_acfcomp = 1;
if (Enabled(ConfProtocomp))
lcp->want_protocomp = 1;
LcpFsm.maxconfig = 10;
}
static void
LcpInitRestartCounter(struct fsm * fp)
{
fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
fp->restart = 5;
}
int
LcpPutConf(int log, u_char *tgt, const struct lcp_opt *o, const char *nm,
const char *arg, ...)
{
va_list ap;
char buf[30];
va_start(ap, arg);
memcpy(tgt, o, o->len);
if (arg == NULL || *arg == '\0')
LogPrintf(log, " %s[%d]\n", nm, o->len);
else {
vsnprintf(buf, sizeof buf, arg, ap);
LogPrintf(log, " %s[%d] %s\n", nm, o->len, buf);
}
va_end(ap);
return o->len;
}
#define PUTN(ty) \
do { \
o.id = ty; \
o.len = 2; \
cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], NULL); \
} while (0)
#define PUTHEX32(ty, arg) \
do { \
o.id = ty; \
o.len = 6; \
*(u_long *)o.data = htonl(arg); \
cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], "0x%08lx", (u_long)arg);\
} while (0)
#define PUTACCMAP(arg) PUTHEX32(TY_ACCMAP, arg)
#define PUTMAGIC(arg) PUTHEX32(TY_MAGICNUM, arg)
#define PUTMRU(arg) \
do { \
o.id = TY_MRU; \
o.len = 4; \
*(u_short *)o.data = htons(arg); \
cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], "%u", arg); \
} while (0)
#define PUTLQR(period) \
do { \
o.id = TY_QUALPROTO; \
o.len = 8; \
*(u_short *)o.data = htons(PROTO_LQR); \
*(u_long *)(o.data+2) = htonl(period); \
cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \
"period %ld", (u_long)period); \
} while (0)
#define PUTPAP() \
do { \
o.id = TY_AUTHPROTO; \
o.len = 4; \
*(u_short *)o.data = htons(PROTO_PAP); \
cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \
"0x%04x (PAP)", PROTO_PAP); \
} while (0)
#define PUTCHAP(val) \
do { \
o.id = TY_AUTHPROTO; \
o.len = 5; \
*(u_short *)o.data = htons(PROTO_CHAP); \
o.data[2] = val; \
cp += LcpPutConf(LogLCP, cp, &o, cftypes[o.id], \
"0x%04x (CHAP 0x%02x)", PROTO_CHAP, val); \
} while (0)
#define PUTMD5CHAP() PUTCHAP(0x05)
#define PUTMSCHAP() PUTCHAP(0x80)
static void
LcpSendConfigReq(struct fsm * fp)
{
u_char *cp;
struct lcpstate *lcp = &LcpInfo;
struct lcp_opt o;
LogPrintf(LogLCP, "LcpSendConfigReq\n");
cp = ReqBuff;
if (!DEV_IS_SYNC) {
if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
PUTN(TY_ACFCOMP);
if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
PUTN(TY_PROTOCOMP);
if (!REJECTED(lcp, TY_ACCMAP))
PUTACCMAP(lcp->want_accmap);
}
if (!REJECTED(lcp, TY_MRU))
PUTMRU(lcp->want_mru);
if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM))
PUTMAGIC(lcp->want_magic);
if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO))
PUTLQR(lcp->want_lqrperiod);
switch (lcp->want_auth) {
case PROTO_PAP:
PUTPAP();
break;
case PROTO_CHAP:
#ifdef HAVE_DES
if (VarMSChap)
PUTMSCHAP(); /* Use MSChap */
else
#endif
PUTMD5CHAP(); /* Use MD5 */
break;
}
FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
}
void
LcpSendProtoRej(u_char * option, int count)
{
struct fsm *fp = &LcpFsm;
LogPrintf(LogLCP, "LcpSendProtoRej\n");
FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count);
}
static void
LcpSendTerminateReq(struct fsm * fp)
{
/* Most thins are done in fsm layer. Nothing to to. */
}
static void
LcpSendTerminateAck(struct fsm * fp)
{
LogPrintf(LogLCP, "LcpSendTerminateAck.\n");
FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
}
static void
LcpLayerStart(struct fsm * fp)
{
LogPrintf(LogLCP, "LcpLayerStart\n");
NewPhase(PHASE_ESTABLISH);
}
static void
StopAllTimers(void)
{
StopTimer(&LcpReportTimer);
StopIdleTimer();
StopTimer(&AuthPapInfo.authtimer);
StopTimer(&AuthChapInfo.authtimer);
StopLqrTimer();
}
static void
LcpLayerFinish(struct fsm * fp)
{
LogPrintf(LogLCP, "LcpLayerFinish\n");
HangupModem(0);
StopAllTimers();
/* We're down at last. Lets tell background and direct mode to get out */
NewPhase(PHASE_DEAD);
LcpInit();
IpcpInit();
CcpInit();
Prompt();
}
static void
LcpLayerUp(struct fsm * fp)
{
LogPrintf(LogLCP, "LcpLayerUp\n");
tun_configure(LcpInfo.his_mru, ModemSpeed());
SetLinkParams(&LcpInfo);
NewPhase(PHASE_AUTHENTICATE);
StartLqm();
StopTimer(&LcpReportTimer);
LcpReportTimer.state = TIMER_STOPPED;
LcpReportTimer.load = 60 * SECTICKS;
LcpReportTimer.func = LcpReportTime;
StartTimer(&LcpReportTimer);
}
static void
LcpLayerDown(struct fsm * fp)
{
StopAllTimers();
OsLinkdown();
LogPrintf(LogLCP, "LcpLayerDown\n");
/*
* OsLinkdown() brings CCP & IPCP down, then waits 'till we go from
* STOPPING to STOPPED. At this point, the FSM gives us a LayerFinish
*/
}
void
LcpUp()
{
FsmUp(&LcpFsm);
LcpFailedMagic = 0;
}
void
LcpDown()
{ /* Sudden death */
LcpFailedMagic = 0;
FsmDown(&LcpFsm);
/* FsmDown() results in a LcpLayerDown() if we're currently open. */
LcpLayerFinish(&LcpFsm);
}
void
LcpOpen(int open_mode)
{
LcpFsm.open_mode = open_mode;
LcpFailedMagic = 0;
FsmOpen(&LcpFsm);
}
void
LcpClose()
{
NewPhase(PHASE_TERMINATE);
OsInterfaceDown(0);
FsmClose(&LcpFsm);
LcpFailedMagic = 0;
}
/*
* XXX: Should validate option length
*/
static void
LcpDecodeConfig(u_char *cp, int plen, int mode_type)
{
int type, length, sz, pos;
u_int32_t *lp, magic, accmap;
u_short mtu, mru, *sp, proto;
struct lqrreq *req;
char request[20], desc[22];
ackp = AckBuff;
nakp = NakBuff;
rejp = RejBuff;
while (plen >= sizeof(struct fsmconfig)) {
type = *cp;
length = cp[1];
if (type < 0 || type >= NCFTYPES)
snprintf(request, sizeof request, " <%d>[%d]", type, length);
else
snprintf(request, sizeof request, " %s[%d]", cftypes[type], length);
switch (type) {
case TY_MRU:
sp = (u_short *) (cp + 2);
mru = htons(*sp);
LogPrintf(LogLCP, "%s %d\n", request, mru);
switch (mode_type) {
case MODE_REQ:
mtu = VarPrefMTU;
if (mtu == 0)
mtu = MAX_MTU;
if (mru > mtu) {
*sp = htons(mtu);
memcpy(nakp, cp, 4);
nakp += 4;
} else if (mru < MIN_MRU) {
*sp = htons(MIN_MRU);
memcpy(nakp, cp, 4);
nakp += 4;
} else {
LcpInfo.his_mru = mru;
memcpy(ackp, cp, 4);
ackp += 4;
}
break;
case MODE_NAK:
if (mru >= MIN_MRU || mru <= MAX_MRU)
LcpInfo.want_mru = mru;
break;
case MODE_REJ:
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_ACCMAP:
lp = (u_int32_t *) (cp + 2);
accmap = htonl(*lp);
LogPrintf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
switch (mode_type) {
case MODE_REQ:
LcpInfo.his_accmap = accmap;
memcpy(ackp, cp, 6);
ackp += 6;
break;
case MODE_NAK:
LcpInfo.want_accmap = accmap;
break;
case MODE_REJ:
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_AUTHPROTO:
sp = (u_short *) (cp + 2);
proto = ntohs(*sp);
switch (proto) {
case PROTO_PAP:
LogPrintf(LogLCP, "%s 0x%04x (PAP)\n", request, proto);
break;
case PROTO_CHAP:
LogPrintf(LogLCP, "%s 0x%04x (CHAP 0x%02x)\n", request, proto, cp[4]);
break;
default:
LogPrintf(LogLCP, "%s 0x%04x\n", request, proto);
break;
}
switch (mode_type) {
case MODE_REQ:
switch (proto) {
case PROTO_PAP:
if (length != 4) {
LogPrintf(LogLCP, " Bad length!\n");
goto reqreject;
}
if (Acceptable(ConfPap)) {
LcpInfo.his_auth = proto;
memcpy(ackp, cp, length);
ackp += length;
} else if (Acceptable(ConfChap)) {
*nakp++ = *cp;
*nakp++ = 5;
*nakp++ = (unsigned char) (PROTO_CHAP >> 8);
*nakp++ = (unsigned char) PROTO_CHAP;
#ifdef HAVE_DES
if (VarMSChap)
*nakp++ = 0x80;
else
#endif
*nakp++ = 5;
} else
goto reqreject;
break;
case PROTO_CHAP:
if (length < 5) {
LogPrintf(LogLCP, " Bad length!\n");
goto reqreject;
}
#ifdef HAVE_DES
if (Acceptable(ConfChap) && (cp[4] == 5 || cp[4] == 0x80))
#else
if (Acceptable(ConfChap) && cp[4] == 5)
#endif
{
LcpInfo.his_auth = proto;
memcpy(ackp, cp, length);
ackp += length;
#ifdef HAVE_DES
VarMSChap = cp[4] == 0x80;
#endif
} else if (Acceptable(ConfPap)) {
*nakp++ = *cp;
*nakp++ = 4;
*nakp++ = (unsigned char) (PROTO_PAP >> 8);
*nakp++ = (unsigned char) PROTO_PAP;
} else
goto reqreject;
break;
default:
LogPrintf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
request, proto);
memcpy(nakp, cp, length);
nakp += length;
break;
}
break;
case MODE_NAK:
switch (proto) {
case PROTO_PAP:
if (Enabled(ConfPap))
LcpInfo.want_auth = PROTO_PAP;
else {
LogPrintf(LogLCP, "Peer will only send PAP (not enabled)\n");
LcpInfo.his_reject |= (1 << type);
}
break;
case PROTO_CHAP:
if (Enabled(ConfChap))
LcpInfo.want_auth = PROTO_CHAP;
else {
LogPrintf(LogLCP, "Peer will only send CHAP (not enabled)\n");
LcpInfo.his_reject |= (1 << type);
}
break;
default:
/* We've been NAK'd with something we don't understand :-( */
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case MODE_REJ:
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_QUALPROTO:
req = (struct lqrreq *) cp;
LogPrintf(LogLCP, "%s proto %x, interval %dms\n",
request, ntohs(req->proto), ntohl(req->period) * 10);
switch (mode_type) {
case MODE_REQ:
if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr))
goto reqreject;
else {
LcpInfo.his_lqrperiod = ntohl(req->period);
if (LcpInfo.his_lqrperiod < 500)
LcpInfo.his_lqrperiod = 500;
req->period = htonl(LcpInfo.his_lqrperiod);
memcpy(ackp, cp, length);
ackp += length;
}
break;
case MODE_NAK:
break;
case MODE_REJ:
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_MAGICNUM:
lp = (u_int32_t *) (cp + 2);
magic = ntohl(*lp);
LogPrintf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
switch (mode_type) {
case MODE_REQ:
if (LcpInfo.want_magic) {
/* Validate magic number */
if (magic == LcpInfo.want_magic) {
LogPrintf(LogLCP, "Magic is same (%08lx) - %d times\n",
(u_long)magic, ++LcpFailedMagic);
LcpInfo.want_magic = GenerateMagic();
memcpy(nakp, cp, 6);
nakp += 6;
ualarm(TICKUNIT * (4 + 4 * LcpFailedMagic), 0);
sigpause(0);
} else {
LcpInfo.his_magic = magic;
memcpy(ackp, cp, length);
ackp += length;
LcpFailedMagic = 0;
}
} else {
LcpInfo.my_reject |= (1 << type);
goto reqreject;
}
break;
case MODE_NAK:
LogPrintf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
LcpInfo.want_magic = GenerateMagic();
break;
case MODE_REJ:
LogPrintf(LogLCP, " Magic 0x%80x is REJected!\n", magic);
LcpInfo.want_magic = 0;
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_PROTOCOMP:
LogPrintf(LogLCP, "%s\n", request);
switch (mode_type) {
case MODE_REQ:
if (Acceptable(ConfProtocomp)) {
LcpInfo.his_protocomp = 1;
memcpy(ackp, cp, 2);
ackp += 2;
} else {
#ifdef OLDMST
/*
* MorningStar before v1.3 needs NAK
*/
memcpy(nakp, cp, 2);
nakp += 2;
#else
memcpy(rejp, cp, 2);
rejp += 2;
LcpInfo.my_reject |= (1 << type);
#endif
}
break;
case MODE_NAK:
case MODE_REJ:
LcpInfo.want_protocomp = 0;
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_ACFCOMP:
LogPrintf(LogLCP, "%s\n", request);
switch (mode_type) {
case MODE_REQ:
if (Acceptable(ConfAcfcomp)) {
LcpInfo.his_acfcomp = 1;
memcpy(ackp, cp, 2);
ackp += 2;
} else {
#ifdef OLDMST
/*
* MorningStar before v1.3 needs NAK
*/
memcpy(nakp, cp, 2);
nakp += 2;
#else
memcpy(rejp, cp, 2);
rejp += 2;
LcpInfo.my_reject |= (1 << type);
#endif
}
break;
case MODE_NAK:
case MODE_REJ:
LcpInfo.want_acfcomp = 0;
LcpInfo.his_reject |= (1 << type);
break;
}
break;
case TY_SDP:
LogPrintf(LogLCP, "%s\n", request);
switch (mode_type) {
case MODE_REQ:
case MODE_NAK:
case MODE_REJ:
break;
}
break;
default:
sz = (sizeof desc - 2) / 2;
if (sz > length - 2)
sz = length - 2;
pos = 0;
desc[0] = sz ? ' ' : '\0';
for (pos = 0; sz--; pos++)
sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
LogPrintf(LogLCP, "%s%s\n", request, desc);
if (mode_type == MODE_REQ) {
reqreject:
if (length > sizeof RejBuff - (rejp - RejBuff)) {
length = sizeof RejBuff - (rejp - RejBuff);
LogPrintf(LogLCP, "Can't REJ length %d - trunating to %d\n",
cp[1], length);
}
memcpy(rejp, cp, length);
rejp += length;
LcpInfo.my_reject |= (1 << type);
if (length != cp[1])
return;
}
break;
}
/* to avoid inf. loop */
if (length == 0) {
LogPrintf(LogLCP, "LCP size zero\n");
break;
}
plen -= length;
cp += length;
}
}
void
LcpInput(struct mbuf * bp)
{
FsmInput(&LcpFsm, bp);
}

82
usr.sbin/ppp/lcp.h Normal file
View File

@ -0,0 +1,82 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: lcp.h,v 1.15 1997/12/04 18:49:28 brian Exp $
*
* TODO:
*/
#define REJECTED(p, x) ((p)->his_reject & (1<<(x)))
struct lcpstate {
u_int16_t his_mru;
u_int32_t his_accmap;
u_int32_t his_magic;
u_int32_t his_lqrperiod;
u_char his_protocomp;
u_char his_acfcomp;
u_short his_auth;
u_short want_mru;
u_int32_t want_accmap;
u_int32_t want_magic;
u_int32_t want_lqrperiod;
u_char want_protocomp;
u_char want_acfcomp;
u_short want_auth;
u_int32_t his_reject; /* Request codes rejected by peer */
u_int32_t my_reject; /* Request codes I have rejected */
u_short auth_iwait;
u_short auth_ineed;
};
#define LCP_MAXCODE CODE_DISCREQ
#define TY_MRU 1 /* Maximum-Receive-Unit */
#define TY_ACCMAP 2 /* Async-Control-Character-Map */
#define TY_AUTHPROTO 3 /* Authentication-Protocol */
#define TY_QUALPROTO 4 /* Quality-Protocol */
#define TY_MAGICNUM 5 /* Magic-Number */
#define TY_RESERVED 6 /* RESERVED */
#define TY_PROTOCOMP 7 /* Protocol-Field-Compression */
#define TY_ACFCOMP 8 /* Address-and-Control-Field-Compression */
#define TY_FCSALT 9 /* FCS-Alternatives */
#define TY_SDP 10 /* Self-Describing-Padding */
#define MAX_LCP_OPT_LEN 10
struct lcp_opt {
u_char id;
u_char len;
u_char data[MAX_LCP_OPT_LEN-2];
};
extern struct lcpstate LcpInfo;
extern struct fsm LcpFsm;
extern void LcpInit(void);
extern void LcpUp(void);
extern void LcpSendProtoRej(u_char *, int);
extern void LcpOpen(int);
extern void LcpClose(void);
extern void LcpDown(void);
extern int LcpPutConf(int, u_char *, const struct lcp_opt *, const char *,
const char *, ...);
extern int ReportLcpStatus(struct cmdargs const *);
extern void LcpInput(struct mbuf *);

39
usr.sbin/ppp/lcpproto.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: lcpproto.h,v 1.9 1997/10/26 01:02:59 brian Exp $
*
* TODO:
*/
/*
* Definition of protocol numbers
*/
#define PROTO_IP 0x0021 /* IP */
#define PROTO_VJUNCOMP 0x002f /* VJ Uncompressed */
#define PROTO_VJCOMP 0x002d /* VJ Compressed */
#define PROTO_ICOMPD 0x00fb /* Individual link compressed */
#define PROTO_COMPD 0x00fd /* Compressed datagram */
#define PROTO_IPCP 0x8021
#define PROTO_ICCP 0x80fb
#define PROTO_CCP 0x80fd
#define PROTO_LCP 0xc021
#define PROTO_PAP 0xc023
#define PROTO_LQR 0xc025
#define PROTO_CHAP 0xc223

169
usr.sbin/ppp/loadalias.c Normal file
View File

@ -0,0 +1,169 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: loadalias.c,v 1.13 1998/01/14 01:23:05 brian Exp $
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <dirent.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "systems.h"
#include "id.h"
#include "loadalias.h"
#include "defs.h"
#include "vars.h"
#define _PATH_ALIAS_PREFIX "/usr/lib/libalias.so.2."
#define off(item) ((int)&(((struct aliasHandlers *)0)->item))
#define entry(a) { off(a), "_" #a }
#ifndef RTLD_NOW
#define RTLD_NOW 1 /* really RTLD_LAZY */
#endif
static struct {
int offset;
const char *name;
} map[] = {
entry(PacketAliasGetFragment),
entry(PacketAliasInit),
entry(PacketAliasIn),
entry(PacketAliasOut),
entry(PacketAliasRedirectAddr),
entry(PacketAliasRedirectPort),
entry(PacketAliasSaveFragment),
entry(PacketAliasSetAddress),
entry(PacketAliasSetMode),
entry(PacketAliasFragmentIn),
{ 0, 0 }
};
static void *dl;
int
loadAliasHandlers(struct aliasHandlers * h)
{
const char *path;
const char *env;
int i;
path = _PATH_ALIAS_PREFIX;
env = getenv("_PATH_ALIAS_PREFIX");
if (env)
if (ID0realuid() == 0)
path = env;
else
LogPrintf(LogALERT, "Ignoring environment _PATH_ALIAS_PREFIX"
" value (%s)\n", env);
dl = dlopen(path, RTLD_NOW);
if (dl == (void *) 0) {
/* Look for _PATH_ALIAS_PREFIX with any number appended */
int plen;
plen = strlen(path);
if (plen && plen < MAXPATHLEN - 1 && path[plen-1] == '.') {
DIR *d;
char p[MAXPATHLEN], *fix;
char *file, *dir;
strcpy(p, path);
if ((file = strrchr(p, '/')) != NULL) {
fix = file;
*file++ = '\0';
dir = p;
} else {
fix = NULL;
file = p;
dir = ".";
}
if ((d = opendir(dir))) {
struct dirent *entry;
int flen;
char *end;
long maxver, ver;
if (fix)
*fix = '/';
maxver = -1;
flen = strlen(file);
while ((entry = readdir(d)))
if (entry->d_namlen > flen && !strncmp(entry->d_name, file, flen)) {
ver = strtol(entry->d_name + flen, &end, 10);
strcpy(p + plen, entry->d_name + flen);
if (ver >= 0 && *end == '\0' && ver > maxver &&
access(p, R_OK) == 0)
maxver = ver;
}
closedir(d);
if (maxver > -1) {
sprintf(p + plen, "%ld", maxver);
dl = dlopen(p, RTLD_NOW);
}
}
}
if (dl == (void *) 0) {
LogPrintf(LogWARN, "_PATH_ALIAS_PREFIX (%s*): Invalid lib: %s\n",
path, dlerror());
return -1;
}
}
for (i = 0; map[i].name; i++) {
*(void **) ((char *) h + map[i].offset) = dlsym(dl, map[i].name);
if (*(void **) ((char *) h + map[i].offset) == (void *) 0) {
LogPrintf(LogWARN, "_PATH_ALIAS (%s*): %s: %s\n", path,
map[i].name, dlerror());
(void) dlclose(dl);
dl = (void *) 0;
return -1;
}
}
VarPacketAliasInit();
return 0;
}
void
unloadAliasHandlers()
{
if (dl) {
dlclose(dl);
dl = (void *) 0;
}
}

45
usr.sbin/ppp/loadalias.h Normal file
View File

@ -0,0 +1,45 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
struct aliasHandlers {
char *(*PacketAliasGetFragment)(char *);
void (*PacketAliasInit)(void);
int (*PacketAliasIn)(char *, int);
int (*PacketAliasOut)(char *, int);
struct alias_link *(*PacketAliasRedirectAddr)(struct in_addr, struct in_addr);
struct alias_link *(*PacketAliasRedirectPort)
(struct in_addr, u_short, struct in_addr, u_short,
struct in_addr, u_short, u_char);
int (*PacketAliasSaveFragment)(char *);
void (*PacketAliasSetAddress)(struct in_addr);
unsigned (*PacketAliasSetMode)(unsigned, unsigned);
void (*PacketAliasFragmentIn)(char *, char *);
};
extern int loadAliasHandlers(struct aliasHandlers *);
extern void unloadAliasHandlers(void);

245
usr.sbin/ppp/log.c Normal file
View File

@ -0,0 +1,245 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: log.c,v 1.24 1997/12/24 09:29:05 brian Exp $
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <stdio.h>
#include <syslog.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
#include "defs.h"
#include "vars.h"
static const char *LogNames[] = {
"Async",
"Carrier",
"CCP",
"Chat",
"Command",
"Connect",
"Debug",
"HDLC",
"ID0",
"IPCP",
"LCP",
"Link",
"LQM",
"Phase",
"TCP/IP",
"Tun",
"Warning",
"Error",
"Alert"
};
#define MSK(n) (1<<((n)-1))
static u_long LogMask = MSK(LogLINK) | MSK(LogCARRIER) | MSK(LogPHASE);
static u_long LogMaskLocal = MSK(LogERROR) | MSK(LogALERT) | MSK(LogWARN);
static int LogTunno = -1;
static int
syslogLevel(int lev)
{
switch (lev) {
case LogDEBUG:return LOG_DEBUG;
case LogWARN:
return LOG_WARNING;
case LogERROR:
return LOG_ERR;
case LogALERT:
return LOG_ALERT;
}
return lev >= LogMIN && lev <= LogMAX ? LOG_INFO : 0;
}
const char *
LogName(int id)
{
return id < LogMIN || id > LogMAX ? "Unknown" : LogNames[id - 1];
}
void
LogKeep(int id)
{
if (id >= LogMIN && id <= LogMAXCONF)
LogMask |= MSK(id);
}
void
LogKeepLocal(int id)
{
if (id >= LogMIN && id <= LogMAXCONF)
LogMaskLocal |= MSK(id);
}
void
LogDiscard(int id)
{
if (id >= LogMIN && id <= LogMAXCONF)
LogMask &= ~MSK(id);
}
void
LogDiscardLocal(int id)
{
if (id >= LogMIN && id <= LogMAXCONF)
LogMaskLocal &= ~MSK(id);
}
void
LogDiscardAll()
{
LogMask = 0;
}
void
LogDiscardAllLocal()
{
LogMaskLocal = 0;
}
int
LogIsKept(int id)
{
if (id < LogMIN || id > LogMAX)
return 0;
if (id > LogMAXCONF)
return LOG_KEPT_LOCAL | LOG_KEPT_SYSLOG;
return ((LogMaskLocal & MSK(id)) ? LOG_KEPT_LOCAL : 0) |
((LogMask & MSK(id)) ? LOG_KEPT_SYSLOG : 0);
}
void
LogOpen(const char *Name)
{
openlog(Name, LOG_PID, LOG_DAEMON);
}
void
LogSetTun(int tunno)
{
LogTunno = tunno;
}
void
LogClose()
{
closelog();
LogTunno = -1;
}
void
LogPrintf(int lev, const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
if (LogIsKept(lev)) {
static char nfmt[200];
if ((LogIsKept(lev) & LOG_KEPT_LOCAL) && VarTerm) {
if ((LogIsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1)
snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s",
LogTunno, LogName(lev), fmt);
else
snprintf(nfmt, sizeof nfmt, "%s: %s", LogName(lev), fmt);
vfprintf(VarTerm, nfmt, ap);
fflush(VarTerm);
}
if ((LogIsKept(lev) & LOG_KEPT_SYSLOG) && (lev != LogWARN || !VarTerm)) {
if ((LogIsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1)
snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s",
LogTunno, LogName(lev), fmt);
else
snprintf(nfmt, sizeof nfmt, "%s: %s", LogName(lev), fmt);
vsyslog(syslogLevel(lev), nfmt, ap);
}
}
va_end(ap);
}
void
LogDumpBp(int lev, const char *hdr, const struct mbuf * bp)
{
if (LogIsKept(lev)) {
char buf[50];
char *b;
u_char *ptr;
int f;
if (hdr && *hdr)
LogPrintf(lev, "%s\n", hdr);
b = buf;
do {
f = bp->cnt;
ptr = MBUF_CTOP(bp);
while (f--) {
sprintf(b, " %02x", (int) *ptr++);
b += 3;
if (b == buf + sizeof buf - 2) {
strcpy(b, "\n");
LogPrintf(lev, buf);
b = buf;
}
}
} while ((bp = bp->next) != NULL);
if (b > buf) {
strcpy(b, "\n");
LogPrintf(lev, buf);
}
}
}
void
LogDumpBuff(int lev, const char *hdr, const u_char * ptr, int n)
{
if (LogIsKept(lev)) {
char buf[50];
char *b;
if (hdr && *hdr)
LogPrintf(lev, "%s\n", hdr);
while (n > 0) {
b = buf;
for (b = buf; b != buf + sizeof buf - 2 && n--; b += 3)
sprintf(b, " %02x", (int) *ptr++);
strcpy(b, "\n");
LogPrintf(lev, buf);
}
}
}

68
usr.sbin/ppp/log.h Normal file
View File

@ -0,0 +1,68 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
#define LogMIN (1)
#define LogASYNC (1) /* syslog(LOG_INFO, ....) */
#define LogCARRIER (2)
#define LogCCP (3)
#define LogCHAT (4)
#define LogCOMMAND (5)
#define LogCONNECT (6)
#define LogDEBUG (7) /* syslog(LOG_DEBUG, ....) */
#define LogHDLC (8)
#define LogID0 (9)
#define LogIPCP (10)
#define LogLCP (11)
#define LogLINK (12)
#define LogLQM (13)
#define LogPHASE (14)
#define LogTCPIP (15)
#define LogTUN (16) /* If set, tun%d is output with each message */
#define LogMAXCONF (16)
#define LogWARN (17) /* Sent to VarTerm else syslog(LOG_WARNING, ) */
#define LogERROR (18) /* syslog(LOG_ERR, ....), + sent to VarTerm */
#define LogALERT (19) /* syslog(LOG_ALERT, ....) */
#define LogMAX (19)
/* The first int arg for all of the following is one of the above values */
extern const char *LogName(int);
extern void LogKeep(int);
extern void LogKeepLocal(int);
extern void LogDiscard(int);
extern void LogDiscardLocal(int);
extern void LogDiscardAll(void);
extern void LogDiscardAllLocal(void);
#define LOG_KEPT_SYSLOG (1) /* Results of LogIsKept() */
#define LOG_KEPT_LOCAL (2) /* Results of LogIsKept() */
extern int LogIsKept(int);
extern void LogOpen(const char *);
extern void LogSetTun(int);
extern void LogClose(void);
extern void LogPrintf(int, const char *,...);
extern void LogDumpBp(int, const char *, const struct mbuf *);
extern void LogDumpBuff(int, const char *, const u_char *, int);

272
usr.sbin/ppp/lqr.c Normal file
View File

@ -0,0 +1,272 @@
/*
* PPP Line Quality Monitoring (LQM) Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: lqr.c,v 1.21 1998/01/11 17:50:40 brian Exp $
*
* o LQR based on RFC1333
*
* TODO:
* o LQM policy
* o Allow user to configure LQM method and interval.
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "lcpproto.h"
#include "lqr.h"
#include "hdlc.h"
#include "lcp.h"
#include "loadalias.h"
#include "vars.h"
struct lqrdata MyLqrData, HisLqrData;
struct lqrsave HisLqrSave;
static struct pppTimer LqrTimer;
static u_long lastpeerin = (u_long) - 1;
static int lqmmethod;
static u_int32_t echoseq;
static u_int32_t gotseq;
static int lqrsendcnt;
struct echolqr {
u_int32_t magic;
u_int32_t signature;
u_int32_t sequence;
};
#define SIGNATURE 0x594e4f54
static void
SendEchoReq(void)
{
struct fsm *fp = &LcpFsm;
struct echolqr *lqr, lqrdata;
if (fp->state == ST_OPENED) {
lqr = &lqrdata;
lqr->magic = htonl(LcpInfo.want_magic);
lqr->signature = htonl(SIGNATURE);
LogPrintf(LogLQM, "Send echo LQR [%d]\n", echoseq);
lqr->sequence = htonl(echoseq++);
FsmOutput(fp, CODE_ECHOREQ, fp->reqid++,
(u_char *) lqr, sizeof(struct echolqr));
}
}
void
RecvEchoLqr(struct mbuf * bp)
{
struct echolqr *lqr;
u_int32_t seq;
if (plength(bp) == sizeof(struct echolqr)) {
lqr = (struct echolqr *) MBUF_CTOP(bp);
if (htonl(lqr->signature) == SIGNATURE) {
seq = ntohl(lqr->sequence);
LogPrintf(LogLQM, "Got echo LQR [%d]\n", ntohl(lqr->sequence));
gotseq = seq;
}
}
}
void
LqrChangeOrder(struct lqrdata * src, struct lqrdata * dst)
{
u_long *sp, *dp;
int n;
sp = (u_long *) src;
dp = (u_long *) dst;
for (n = 0; n < sizeof(struct lqrdata) / sizeof(u_long); n++)
*dp++ = ntohl(*sp++);
}
static void
SendLqrReport(void *v)
{
struct mbuf *bp;
StopTimer(&LqrTimer);
if (lqmmethod & LQM_LQR) {
if (lqrsendcnt > 5) {
/*
* XXX: Should implement LQM strategy
*/
LogPrintf(LogPHASE, "** 1 Too many ECHO packets are lost. **\n");
lqmmethod = 0; /* Prevent rcursion via LcpClose() */
reconnect(RECON_TRUE);
LcpClose();
} else {
bp = mballoc(sizeof(struct lqrdata), MB_LQR);
HdlcOutput(PRI_LINK, PROTO_LQR, bp);
lqrsendcnt++;
}
} else if (lqmmethod & LQM_ECHO) {
if (echoseq - gotseq > 5) {
LogPrintf(LogPHASE, "** 2 Too many ECHO packets are lost. **\n");
lqmmethod = 0; /* Prevent rcursion via LcpClose() */
reconnect(RECON_TRUE);
LcpClose();
} else
SendEchoReq();
}
if (lqmmethod && Enabled(ConfLqr))
StartTimer(&LqrTimer);
}
void
LqrInput(struct mbuf * bp)
{
int len;
u_char *cp;
struct lqrdata *lqr;
len = plength(bp);
if (len != sizeof(struct lqrdata)) {
pfree(bp);
return;
}
if (!Acceptable(ConfLqr)) {
bp->offset -= 2;
bp->cnt += 2;
cp = MBUF_CTOP(bp);
LcpSendProtoRej(cp, bp->cnt);
} else {
cp = MBUF_CTOP(bp);
lqr = (struct lqrdata *) cp;
if (ntohl(lqr->MagicNumber) != LcpInfo.his_magic) {
LogPrintf(LogERROR, "LqrInput: magic %x != expecting %x\n",
ntohl(lqr->MagicNumber), LcpInfo.his_magic);
pfree(bp);
return;
}
/*
* Convert byte order and save into our strage
*/
LqrChangeOrder(lqr, &HisLqrData);
LqrDump("LqrInput", &HisLqrData);
lqrsendcnt = 0; /* we have received LQR from peer */
/*
* Generate LQR responce to peer, if i) We are not running LQR timer. ii)
* Two successive LQR's PeerInLQRs are same.
*/
if (LqrTimer.load == 0 || lastpeerin == HisLqrData.PeerInLQRs) {
lqmmethod |= LQM_LQR;
SendLqrReport(0);
}
lastpeerin = HisLqrData.PeerInLQRs;
}
pfree(bp);
}
/*
* When LCP is reached to opened state, We'll start LQM activity.
*/
void
StartLqm()
{
struct lcpstate *lcp = &LcpInfo;
int period;
lqrsendcnt = 0; /* start waiting all over for ECHOs */
echoseq = 0;
gotseq = 0;
lqmmethod = LQM_ECHO;
if (Enabled(ConfLqr))
lqmmethod |= LQM_LQR;
StopTimer(&LqrTimer);
LogPrintf(LogLQM, "LQM method = %d\n", lqmmethod);
if (lcp->his_lqrperiod || lcp->want_lqrperiod) {
/*
* We need to run timer. Let's figure out period.
*/
period = lcp->his_lqrperiod ? lcp->his_lqrperiod : lcp->want_lqrperiod;
StopTimer(&LqrTimer);
LqrTimer.state = TIMER_STOPPED;
LqrTimer.load = period * SECTICKS / 100;
LqrTimer.func = SendLqrReport;
SendLqrReport(0);
StartTimer(&LqrTimer);
LogPrintf(LogLQM, "Will send LQR every %d.%d secs\n",
period / 100, period % 100);
} else {
LogPrintf(LogLQM, "LQR is not activated.\n");
}
}
void
StopLqrTimer()
{
StopTimer(&LqrTimer);
}
void
StopLqr(int method)
{
LogPrintf(LogLQM, "StopLqr method = %x\n", method);
if (method == LQM_LQR)
LogPrintf(LogLQM, "Stop sending LQR, Use LCP ECHO instead.\n");
if (method == LQM_ECHO)
LogPrintf(LogLQM, "Stop sending LCP ECHO.\n");
lqmmethod &= ~method;
if (lqmmethod)
SendLqrReport(0);
else
StopTimer(&LqrTimer);
}
void
LqrDump(const char *message, const struct lqrdata * lqr)
{
if (LogIsKept(LogLQM)) {
LogPrintf(LogLQM, "%s:\n", message);
LogPrintf(LogLQM, " Magic: %08x LastOutLQRs: %08x\n",
lqr->MagicNumber, lqr->LastOutLQRs);
LogPrintf(LogLQM, " LastOutPackets: %08x LastOutOctets: %08x\n",
lqr->LastOutPackets, lqr->LastOutOctets);
LogPrintf(LogLQM, " PeerInLQRs: %08x PeerInPackets: %08x\n",
lqr->PeerInLQRs, lqr->PeerInPackets);
LogPrintf(LogLQM, " PeerInDiscards: %08x PeerInErrors: %08x\n",
lqr->PeerInDiscards, lqr->PeerInErrors);
LogPrintf(LogLQM, " PeerInOctets: %08x PeerOutLQRs: %08x\n",
lqr->PeerInOctets, lqr->PeerOutLQRs);
LogPrintf(LogLQM, " PeerOutPackets: %08x PeerOutOctets: %08x\n",
lqr->PeerOutPackets, lqr->PeerOutOctets);
}
}

64
usr.sbin/ppp/lqr.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: lqr.h,v 1.11 1998/01/11 17:50:42 brian Exp $
*
* TODO:
*/
/*
* Structure of LQR packet defined in RFC1333
*/
struct lqrdata {
u_int32_t MagicNumber;
u_int32_t LastOutLQRs;
u_int32_t LastOutPackets;
u_int32_t LastOutOctets;
u_int32_t PeerInLQRs;
u_int32_t PeerInPackets;
u_int32_t PeerInDiscards;
u_int32_t PeerInErrors;
u_int32_t PeerInOctets;
u_int32_t PeerOutLQRs;
u_int32_t PeerOutPackets;
u_int32_t PeerOutOctets;
};
struct lqrsave {
u_int32_t SaveInLQRs;
u_int32_t SaveInPackets;
u_int32_t SaveInDiscards;
u_int32_t SaveInErrors;
u_int32_t SaveInOctets;
};
extern struct lqrdata MyLqrData, HisLqrData;
extern struct lqrsave HisLqrSave;
/*
* We support LQR and ECHO as LQM method
*/
#define LQM_LQR 1
#define LQM_ECHO 2
extern void LqrDump(const char *, const struct lqrdata *);
extern void LqrChangeOrder(struct lqrdata *, struct lqrdata *);
extern void StartLqm(void);
extern void StopLqr(int);
extern void StopLqrTimer(void);
extern void RecvEchoLqr(struct mbuf *);
extern void LqrInput(struct mbuf *);

1101
usr.sbin/ppp/main.c Normal file

File diff suppressed because it is too large Load Diff

31
usr.sbin/ppp/main.h Normal file
View File

@ -0,0 +1,31 @@
/*
* User Process PPP
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: main.h,v 1.8 1997/11/22 03:37:39 brian Exp $
*
*/
extern int TermMode;
extern int tunno;
extern void Cleanup(int);
extern void TtyTermMode(void);
extern void PacketMode(int);
extern void TtyOldMode(void);
extern void TtyCommandMode(int);

175
usr.sbin/ppp/mbuf.c Normal file
View File

@ -0,0 +1,175 @@
/*
* PPP Memory handling module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: mbuf.c,v 1.12 1997/12/28 02:56:42 brian Exp $
*
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "loadalias.h"
#include "vars.h"
#include "server.h"
static struct memmap {
struct mbuf *queue;
int count;
} MemMap[MB_MAX + 2];
static int totalalloced;
int
plength(struct mbuf * bp)
{
int len;
for (len = 0; bp; bp = bp->next)
len += bp->cnt;
return (len);
}
struct mbuf *
mballoc(int cnt, int type)
{
u_char *p;
struct mbuf *bp;
if (type > MB_MAX)
LogPrintf(LogERROR, "Bad mbuf type %d\n", type);
bp = (struct mbuf *) malloc(sizeof(struct mbuf));
if (bp == NULL) {
LogPrintf(LogALERT, "failed to allocate memory: %u\n", sizeof(struct mbuf));
ServerClose();
exit(1);
}
memset(bp, '\0', sizeof(struct mbuf));
p = (u_char *) malloc(cnt);
if (p == NULL) {
LogPrintf(LogALERT, "failed to allocate memory: %d\n", cnt);
ServerClose();
exit(1);
}
MemMap[type].count += cnt;
totalalloced += cnt;
bp->base = p;
bp->size = bp->cnt = cnt;
bp->type = type;
bp->pnext = NULL;
return (bp);
}
struct mbuf *
mbfree(struct mbuf * bp)
{
struct mbuf *nbp;
if (bp) {
nbp = bp->next;
MemMap[bp->type].count -= bp->size;
totalalloced -= bp->size;
free(bp->base);
free(bp);
return (nbp);
}
return (bp);
}
void
pfree(struct mbuf * bp)
{
while (bp)
bp = mbfree(bp);
}
struct mbuf *
mbread(struct mbuf * bp, u_char * ptr, int len)
{
int nb;
while (bp && len > 0) {
if (len > bp->cnt)
nb = bp->cnt;
else
nb = len;
memcpy(ptr, MBUF_CTOP(bp), nb);
ptr += nb;
bp->cnt -= nb;
len -= nb;
bp->offset += nb;
if (bp->cnt == 0) {
#ifdef notdef
bp = bp->next;
#else
bp = mbfree(bp);
#endif
}
}
return (bp);
}
void
mbwrite(struct mbuf * bp, u_char * ptr, int cnt)
{
int plen;
int nb;
plen = plength(bp);
if (plen < cnt)
cnt = plen;
while (cnt > 0) {
nb = (cnt < bp->cnt) ? cnt : bp->cnt;
memcpy(MBUF_CTOP(bp), ptr, nb);
cnt -= bp->cnt;
bp = bp->next;
}
}
int
ShowMemMap(struct cmdargs const *arg)
{
int i;
if (!VarTerm)
return 1;
for (i = 0; i <= MB_MAX; i += 2)
fprintf(VarTerm, "%d: %d %d: %d\n",
i, MemMap[i].count, i + 1, MemMap[i + 1].count);
return 0;
}
void
LogMemory()
{
LogPrintf(LogDEBUG, "LogMemory: mem alloced: %d\n", totalalloced);
LogPrintf(LogDEBUG, "LogMemory: 1: %d 2: %d 3: %d 4: %d\n",
MemMap[1].count, MemMap[2].count, MemMap[3].count, MemMap[4].count);
LogPrintf(LogDEBUG, "LogMemory: 5: %d 6: %d 7: %d 8: %d\n",
MemMap[5].count, MemMap[6].count, MemMap[7].count, MemMap[8].count);
}

60
usr.sbin/ppp/mbuf.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: mbuf.h,v 1.10 1997/12/03 10:23:50 brian Exp $
*
* TODO:
*/
struct mbuf {
u_char *base; /* pointer to top of buffer space */
short size; /* size allocated from base */
short offset; /* offset to start position */
short cnt; /* available byte count in buffer */
short type;
struct mbuf *next; /* link to next mbuf */
struct mbuf *pnext; /* link to next packet */
};
struct mqueue {
struct mbuf *top;
struct mbuf *last;
int qlen;
};
#define MBUF_CTOP(bp) (bp->base + bp->offset)
#define MB_ASYNC 1
#define MB_FSM 2
#define MB_HDLCOUT 3
#define MB_IPIN 4
#define MB_ECHO 5
#define MB_LQR 6
#define MB_MODEM 7
#define MB_VJCOMP 8
#define MB_LOG 9
#define MB_IPQ 10
#define MB_MAX MB_IPQ
extern int plength(struct mbuf *);
extern struct mbuf *mballoc(int, int);
extern struct mbuf *mbfree(struct mbuf *);
extern void pfree(struct mbuf *);
extern void mbwrite(struct mbuf *, u_char *, int);
extern struct mbuf *mbread(struct mbuf *, u_char *, int);
extern void LogMemory(void);
extern int ShowMemMap(struct cmdargs const *);

947
usr.sbin/ppp/modem.c Normal file
View File

@ -0,0 +1,947 @@
/*
* PPP Modem handling module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: modem.c,v 1.76 1998/01/21 02:15:22 brian Exp $
*
* TODO:
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <unistd.h>
#include <utmp.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "id.h"
#include "timer.h"
#include "fsm.h"
#include "hdlc.h"
#include "lcp.h"
#include "ip.h"
#include "modem.h"
#include "loadalias.h"
#include "vars.h"
#include "main.h"
#include "chat.h"
#include "throughput.h"
#ifdef __OpenBSD__
#include <util.h>
#else
#include <libutil.h>
#endif
#ifndef O_NONBLOCK
#ifdef O_NDELAY
#define O_NONBLOCK O_NDELAY
#endif
#endif
static int mbits; /* Current DCD status */
static int connect_count;
static struct pppTimer ModemTimer;
#define Online (mbits & TIOCM_CD)
static struct mbuf *modemout;
static struct mqueue OutputQueues[PRI_LINK + 1];
static int dev_is_modem;
static struct pppThroughput throughput;
static void CloseLogicalModem(void);
void
Enqueue(struct mqueue * queue, struct mbuf * bp)
{
if (queue->last) {
queue->last->pnext = bp;
queue->last = bp;
} else
queue->last = queue->top = bp;
queue->qlen++;
LogPrintf(LogDEBUG, "Enqueue: len = %d\n", queue->qlen);
}
struct mbuf *
Dequeue(struct mqueue *queue)
{
struct mbuf *bp;
LogPrintf(LogDEBUG, "Dequeue: len = %d\n", queue->qlen);
bp = queue->top;
if (bp) {
queue->top = queue->top->pnext;
queue->qlen--;
if (queue->top == NULL) {
queue->last = queue->top;
if (queue->qlen)
LogPrintf(LogERROR, "Dequeue: Not zero (%d)!!!\n", queue->qlen);
}
}
return (bp);
}
void
SequenceQueues()
{
LogPrintf(LogDEBUG, "SequenceQueues\n");
while (OutputQueues[PRI_NORMAL].qlen)
Enqueue(OutputQueues + PRI_LINK, Dequeue(OutputQueues + PRI_NORMAL));
}
static struct speeds {
int nspeed;
speed_t speed;
} speeds[] = {
#ifdef B50
{ 50, B50, },
#endif
#ifdef B75
{ 75, B75, },
#endif
#ifdef B110
{ 110, B110, },
#endif
#ifdef B134
{ 134, B134, },
#endif
#ifdef B150
{ 150, B150, },
#endif
#ifdef B200
{ 200, B200, },
#endif
#ifdef B300
{ 300, B300, },
#endif
#ifdef B600
{ 600, B600, },
#endif
#ifdef B1200
{ 1200, B1200, },
#endif
#ifdef B1800
{ 1800, B1800, },
#endif
#ifdef B2400
{ 2400, B2400, },
#endif
#ifdef B4800
{ 4800, B4800, },
#endif
#ifdef B9600
{ 9600, B9600, },
#endif
#ifdef B19200
{ 19200, B19200, },
#endif
#ifdef B38400
{ 38400, B38400, },
#endif
#ifndef _POSIX_SOURCE
#ifdef B7200
{ 7200, B7200, },
#endif
#ifdef B14400
{ 14400, B14400, },
#endif
#ifdef B28800
{ 28800, B28800, },
#endif
#ifdef B57600
{ 57600, B57600, },
#endif
#ifdef B76800
{ 76800, B76800, },
#endif
#ifdef B115200
{ 115200, B115200, },
#endif
#ifdef B230400
{ 230400, B230400, },
#endif
#ifdef EXTA
{ 19200, EXTA, },
#endif
#ifdef EXTB
{ 38400, EXTB, },
#endif
#endif /* _POSIX_SOURCE */
{ 0, 0 }
};
static int
SpeedToInt(speed_t speed)
{
struct speeds *sp;
for (sp = speeds; sp->nspeed; sp++) {
if (sp->speed == speed) {
return (sp->nspeed);
}
}
return 0;
}
speed_t
IntToSpeed(int nspeed)
{
struct speeds *sp;
for (sp = speeds; sp->nspeed; sp++) {
if (sp->nspeed == nspeed) {
return (sp->speed);
}
}
return B0;
}
void
DownConnection()
{
LogPrintf(LogPHASE, "Disconnected!\n");
LcpDown();
}
/*
* ModemTimeout() watches DCD signal and notifies if it's status is changed.
*
*/
void
ModemTimeout(void *data)
{
int ombits = mbits;
int change;
StopTimer(&ModemTimer);
StartTimer(&ModemTimer);
if (dev_is_modem) {
if (modem >= 0) {
if (ioctl(modem, TIOCMGET, &mbits) < 0) {
LogPrintf(LogPHASE, "ioctl error (%s)!\n", strerror(errno));
DownConnection();
return;
}
} else
mbits = 0;
change = ombits ^ mbits;
if (change & TIOCM_CD) {
if (Online) {
LogPrintf(LogDEBUG, "ModemTimeout: offline -> online\n");
/*
* In dedicated mode, start packet mode immediate after we detected
* carrier.
*/
if (mode & MODE_DEDICATED)
PacketMode(VarOpenMode);
} else {
LogPrintf(LogDEBUG, "ModemTimeout: online -> offline\n");
reconnect(RECON_TRUE);
DownConnection();
}
}
else
LogPrintf(LogDEBUG, "ModemTimeout: Still %sline\n",
Online ? "on" : "off");
} else if (!Online) {
/* mbits was set to zero in OpenModem() */
mbits = TIOCM_CD;
}
}
static void
StartModemTimer(void)
{
StopTimer(&ModemTimer);
ModemTimer.state = TIMER_STOPPED;
ModemTimer.load = SECTICKS;
ModemTimer.func = ModemTimeout;
LogPrintf(LogDEBUG, "ModemTimer using ModemTimeout() - %p\n", ModemTimeout);
StartTimer(&ModemTimer);
}
static struct parity {
const char *name;
const char *name1;
int set;
} validparity[] = {
{ "even", "P_EVEN", CS7 | PARENB },
{ "odd", "P_ODD", CS7 | PARENB | PARODD },
{ "none", "P_ZERO", CS8 },
{ NULL, 0 },
};
static int
GetParityValue(const char *str)
{
struct parity *pp;
for (pp = validparity; pp->name; pp++) {
if (strcasecmp(pp->name, str) == 0 ||
strcasecmp(pp->name1, str) == 0) {
return VarParity = pp->set;
}
}
return (-1);
}
int
ChangeParity(const char *str)
{
struct termios rstio;
int val;
val = GetParityValue(str);
if (val > 0) {
VarParity = val;
tcgetattr(modem, &rstio);
rstio.c_cflag &= ~(CSIZE | PARODD | PARENB);
rstio.c_cflag |= val;
tcsetattr(modem, TCSADRAIN, &rstio);
return 0;
}
LogPrintf(LogWARN, "ChangeParity: %s: Invalid parity\n", str);
return -1;
}
static int
OpenConnection(char *host, char *port)
{
struct sockaddr_in dest;
int sock;
struct hostent *hp;
struct servent *sp;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr(host);
if (dest.sin_addr.s_addr == INADDR_NONE) {
hp = gethostbyname(host);
if (hp) {
memcpy(&dest.sin_addr.s_addr, hp->h_addr_list[0], 4);
} else {
LogPrintf(LogWARN, "OpenConnection: unknown host: %s\n", host);
return (-1);
}
}
dest.sin_port = htons(atoi(port));
if (dest.sin_port == 0) {
sp = getservbyname(port, "tcp");
if (sp) {
dest.sin_port = sp->s_port;
} else {
LogPrintf(LogWARN, "OpenConnection: unknown service: %s\n", port);
return (-1);
}
}
LogPrintf(LogPHASE, "Connecting to %s:%s\n", host, port);
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
return (sock);
}
if (connect(sock, (struct sockaddr *)&dest, sizeof dest) < 0) {
LogPrintf(LogWARN, "OpenConnection: connection failed.\n");
return (-1);
}
LogPrintf(LogDEBUG, "OpenConnection: modem fd is %d.\n", sock);
return (sock);
}
static char fn[MAXPATHLEN];
static int
LockModem(void)
{
int res;
FILE *lockfile;
if (*VarDevice != '/')
return 0;
if (!(mode & MODE_DIRECT) && (res = ID0uu_lock(VarBaseDevice)) != UU_LOCK_OK) {
if (res == UU_LOCK_INUSE)
LogPrintf(LogPHASE, "Modem %s is in use\n", VarDevice);
else
LogPrintf(LogPHASE, "Modem %s is in use: uu_lock: %s\n",
VarDevice, uu_lockerr(res));
return (-1);
}
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, VarBaseDevice);
lockfile = ID0fopen(fn, "w");
if (lockfile != NULL) {
fprintf(lockfile, "tun%d\n", tunno);
fclose(lockfile);
}
#ifndef RELEASE_CRUNCH
else
LogPrintf(LogALERT, "Warning: Can't create %s: %s\n", fn, strerror(errno));
#endif
return 0;
}
static void
UnlockModem(void)
{
if (*VarDevice != '/')
return;
snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, VarBaseDevice);
#ifndef RELEASE_CRUNCH
if (ID0unlink(fn) == -1)
LogPrintf(LogALERT, "Warning: Can't remove %s: %s\n", fn, strerror(errno));
#else
ID0unlink(fn);
#endif
if (!(mode & MODE_DIRECT) && ID0uu_unlock(VarBaseDevice) == -1)
LogPrintf(LogALERT, "Warning: Can't uu_unlock %s\n", fn);
}
static void
HaveModem(void)
{
throughput_start(&throughput);
connect_count++;
LogPrintf(LogPHASE, "Connected!\n");
}
static struct termios modemios;
int
OpenModem()
{
struct termios rstio;
int oldflag;
char *host, *port;
char *cp;
char tmpDeviceList[sizeof VarDeviceList];
char *tmpDevice;
if (modem >= 0)
LogPrintf(LogDEBUG, "OpenModem: Modem is already open!\n");
/* We're going back into "term" mode */
else if (mode & MODE_DIRECT) {
struct cmdargs arg;
arg.cmd = NULL;
arg.data = (const void *)VAR_DEVICE;
if (isatty(STDIN_FILENO)) {
LogPrintf(LogDEBUG, "OpenModem(direct): Modem is a tty\n");
cp = ttyname(STDIN_FILENO);
arg.argc = 1;
arg.argv = (char const *const *)&cp;
SetVariable(&arg);
if (LockModem() == -1) {
close(STDIN_FILENO);
return -1;
}
modem = STDIN_FILENO;
HaveModem();
} else {
LogPrintf(LogDEBUG, "OpenModem(direct): Modem is not a tty\n");
arg.argc = 0;
arg.argv = NULL;
SetVariable(&arg);
/* We don't call ModemTimeout() with this type of connection */
HaveModem();
return modem = STDIN_FILENO;
}
} else {
strncpy(tmpDeviceList, VarDeviceList, sizeof tmpDeviceList - 1);
tmpDeviceList[sizeof tmpDeviceList - 1] = '\0';
for(tmpDevice=strtok(tmpDeviceList, ","); tmpDevice && (modem < 0);
tmpDevice=strtok(NULL,",")) {
strncpy(VarDevice, tmpDevice, sizeof VarDevice - 1);
VarDevice[sizeof VarDevice - 1]= '\0';
VarBaseDevice = strrchr(VarDevice, '/');
VarBaseDevice = VarBaseDevice ? VarBaseDevice + 1 : "";
if (strncmp(VarDevice, "/dev/", 5) == 0) {
if (LockModem() == -1) {
modem = -1;
}
else {
modem = ID0open(VarDevice, O_RDWR | O_NONBLOCK);
if (modem < 0) {
LogPrintf(LogERROR, "OpenModem failed: %s: %s\n", VarDevice,
strerror(errno));
UnlockModem();
modem = -1;
}
else {
HaveModem();
LogPrintf(LogDEBUG, "OpenModem: Modem is %s\n", VarDevice);
}
}
} else {
/* PPP over TCP */
cp = strchr(VarDevice, ':');
if (cp) {
*cp = '\0';
host = VarDevice;
port = cp + 1;
if (*host && *port) {
modem = OpenConnection(host, port);
*cp = ':'; /* Don't destroy VarDevice */
if (modem < 0)
return (-1);
HaveModem();
LogPrintf(LogDEBUG, "OpenModem: Modem is socket %s\n", VarDevice);
} else {
*cp = ':'; /* Don't destroy VarDevice */
LogPrintf(LogERROR, "Invalid host:port: \"%s\"\n", VarDevice);
return (-1);
}
} else {
LogPrintf(LogERROR,
"Device (%s) must be in /dev or be a host:port pair\n",
VarDevice);
return (-1);
}
}
}
if (modem < 0) return modem;
}
/*
* If we are working on tty device, change it's mode into the one desired
* for further operation. In this implementation, we assume that modem is
* configuted to use CTS/RTS flow control.
*/
mbits = 0;
dev_is_modem = isatty(modem) || DEV_IS_SYNC;
if (DEV_IS_SYNC)
nointr_sleep(1);
if (dev_is_modem && !DEV_IS_SYNC) {
tcgetattr(modem, &rstio);
modemios = rstio;
LogPrintf(LogDEBUG, "OpenModem: modem = %d\n", modem);
LogPrintf(LogDEBUG, "OpenModem: modem (get): iflag = %x, oflag = %x,"
" cflag = %x\n", rstio.c_iflag, rstio.c_oflag, rstio.c_cflag);
cfmakeraw(&rstio);
if (VarCtsRts)
rstio.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
else {
rstio.c_cflag |= CLOCAL;
rstio.c_iflag |= IXOFF;
}
rstio.c_iflag |= IXON;
if (!(mode & MODE_DEDICATED))
rstio.c_cflag |= HUPCL;
if ((mode & MODE_DIRECT) == 0) {
/*
* If we are working as direct mode, don't change tty speed.
*/
rstio.c_cflag &= ~(CSIZE | PARODD | PARENB);
rstio.c_cflag |= VarParity;
if (cfsetspeed(&rstio, IntToSpeed(VarSpeed)) == -1) {
LogPrintf(LogWARN, "Unable to set modem speed (modem %d to %d)\n",
modem, VarSpeed);
}
}
tcsetattr(modem, TCSADRAIN, &rstio);
LogPrintf(LogDEBUG, "modem (put): iflag = %x, oflag = %x, cflag = %x\n",
rstio.c_iflag, rstio.c_oflag, rstio.c_cflag);
if (!(mode & MODE_DIRECT))
if (ioctl(modem, TIOCMGET, &mbits)) {
LogPrintf(LogERROR, "OpenModem: Cannot get modem status: %s\n",
strerror(errno));
CloseLogicalModem();
return (-1);
}
LogPrintf(LogDEBUG, "OpenModem: modem control = %o\n", mbits);
oldflag = fcntl(modem, F_GETFL, 0);
if (oldflag < 0) {
LogPrintf(LogERROR, "OpenModem: Cannot get modem flags: %s\n",
strerror(errno));
CloseLogicalModem();
return (-1);
}
(void) fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK);
}
StartModemTimer();
return (modem);
}
int
ModemSpeed()
{
struct termios rstio;
tcgetattr(modem, &rstio);
return (SpeedToInt(cfgetispeed(&rstio)));
}
/*
* Put modem tty line into raw mode which is necessary in packet mode operation
*/
int
RawModem()
{
struct termios rstio;
int oldflag;
if (!isatty(modem) || DEV_IS_SYNC)
return (0);
if (!(mode & MODE_DIRECT) && modem >= 0 && !Online) {
LogPrintf(LogDEBUG, "RawModem: mode = %d, modem = %d, mbits = %x\n", mode, modem, mbits);
}
tcgetattr(modem, &rstio);
cfmakeraw(&rstio);
if (VarCtsRts)
rstio.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
else
rstio.c_cflag |= CLOCAL;
if (!(mode & MODE_DEDICATED))
rstio.c_cflag |= HUPCL;
tcsetattr(modem, TCSADRAIN, &rstio);
oldflag = fcntl(modem, F_GETFL, 0);
if (oldflag < 0)
return (-1);
(void) fcntl(modem, F_SETFL, oldflag | O_NONBLOCK);
return (0);
}
static void
UnrawModem(void)
{
int oldflag;
if (isatty(modem) && !DEV_IS_SYNC) {
tcsetattr(modem, TCSAFLUSH, &modemios);
oldflag = fcntl(modem, F_GETFL, 0);
if (oldflag < 0)
return;
(void) fcntl(modem, F_SETFL, oldflag & ~O_NONBLOCK);
}
}
void
ModemAddInOctets(int n)
{
throughput_addin(&throughput, n);
}
void
ModemAddOutOctets(int n)
{
throughput_addout(&throughput, n);
}
static void
ClosePhysicalModem(void)
{
LogPrintf(LogDEBUG, "ClosePhysicalModem\n");
close(modem);
modem = -1;
throughput_log(&throughput, LogPHASE, "Modem");
}
void
HangupModem(int flag)
{
struct termios tio;
LogPrintf(LogDEBUG, "Hangup modem (%s)\n", modem >= 0 ? "open" : "closed");
if (modem < 0)
return;
StopTimer(&ModemTimer);
throughput_stop(&throughput);
if (TermMode) {
LogPrintf(LogDEBUG, "HangupModem: Not in 'term' mode\n");
return;
}
if (!isatty(modem)) {
mbits &= ~TIOCM_DTR;
ClosePhysicalModem();
return;
}
if (modem >= 0 && Online) {
mbits &= ~TIOCM_DTR;
tcgetattr(modem, &tio);
if (cfsetspeed(&tio, B0) == -1) {
LogPrintf(LogWARN, "Unable to set modem to speed 0\n");
}
tcsetattr(modem, TCSANOW, &tio);
nointr_sleep(1);
}
if (modem >= 0) {
char ScriptBuffer[SCRIPT_LEN];
strncpy(ScriptBuffer, VarHangupScript, sizeof ScriptBuffer - 1);
ScriptBuffer[sizeof ScriptBuffer - 1] = '\0';
LogPrintf(LogDEBUG, "HangupModem: Script: %s\n", ScriptBuffer);
if (flag || !(mode & MODE_DEDICATED)) {
DoChat(ScriptBuffer);
tcflush(modem, TCIOFLUSH);
UnrawModem();
CloseLogicalModem();
} else {
/*
* If we are working as dedicated mode, never close it until we are
* directed to quit program.
*/
mbits |= TIOCM_DTR;
ioctl(modem, TIOCMSET, &mbits);
DoChat(ScriptBuffer);
}
}
}
static void
CloseLogicalModem(void)
{
LogPrintf(LogDEBUG, "CloseLogicalModem\n");
if (modem >= 0) {
ClosePhysicalModem();
if (Utmp) {
struct utmp ut;
strncpy(ut.ut_line, VarBaseDevice, sizeof ut.ut_line - 1);
ut.ut_line[sizeof ut.ut_line - 1] = '\0';
if (logout(ut.ut_line))
logwtmp(ut.ut_line, "", "");
else
LogPrintf(LogERROR, "CloseLogicalModem: No longer logged in on %s\n",
ut.ut_line);
Utmp = 0;
}
UnlockModem();
}
}
/*
* Write to modem. Actualy, requested packets are queued, and goes out
* to the line when ModemStartOutput() is called.
*/
void
WriteModem(int pri, const char *ptr, int count)
{
struct mbuf *bp;
bp = mballoc(count, MB_MODEM);
memcpy(MBUF_CTOP(bp), ptr, count);
/*
* Should be NORMAL and LINK only. All IP frames get here marked NORMAL.
*/
Enqueue(&OutputQueues[pri], bp);
}
void
ModemOutput(int pri, struct mbuf * bp)
{
struct mbuf *wp;
int len;
len = plength(bp);
wp = mballoc(len, MB_MODEM);
mbread(bp, MBUF_CTOP(wp), len);
Enqueue(&OutputQueues[pri], wp);
ModemStartOutput(modem);
}
int
ModemQlen()
{
struct mqueue *queue;
int len = 0;
int i;
for (i = PRI_NORMAL; i <= PRI_LINK; i++) {
queue = &OutputQueues[i];
len += queue->qlen;
}
return (len);
}
void
ModemStartOutput(int fd)
{
struct mqueue *queue;
int nb, nw;
int i;
if (modemout == NULL && ModemQlen() == 0)
IpStartOutput();
if (modemout == NULL) {
i = PRI_LINK;
for (queue = &OutputQueues[PRI_LINK]; queue >= OutputQueues; queue--) {
if (queue->top) {
modemout = Dequeue(queue);
if (LogIsKept(LogDEBUG)) {
if (i > PRI_NORMAL) {
struct mqueue *q;
q = &OutputQueues[0];
LogPrintf(LogDEBUG, "ModemStartOutput: Output from queue %d,"
" normal has %d\n", i, q->qlen);
}
LogPrintf(LogDEBUG, "ModemStartOutput: Dequeued %d\n", i);
}
break;
}
i--;
}
}
if (modemout) {
nb = modemout->cnt;
if (nb > 1600)
nb = 1600;
nw = write(fd, MBUF_CTOP(modemout), nb);
LogPrintf(LogDEBUG, "ModemStartOutput: wrote: %d(%d)\n", nw, nb);
LogDumpBuff(LogDEBUG, "ModemStartOutput: modem write",
MBUF_CTOP(modemout), nb);
if (nw > 0) {
modemout->cnt -= nw;
modemout->offset += nw;
if (modemout->cnt == 0) {
modemout = mbfree(modemout);
LogPrintf(LogDEBUG, "ModemStartOutput: mbfree\n");
}
} else if (nw < 0) {
if (errno != EAGAIN) {
LogPrintf(LogERROR, "modem write (%d): %s\n", modem, strerror(errno));
reconnect(RECON_TRUE);
DownConnection();
}
}
}
}
int
DialModem()
{
char ScriptBuffer[SCRIPT_LEN];
int excode;
strncpy(ScriptBuffer, VarDialScript, sizeof ScriptBuffer - 1);
ScriptBuffer[sizeof ScriptBuffer - 1] = '\0';
if ((excode = DoChat(ScriptBuffer)) > 0) {
if (VarTerm)
fprintf(VarTerm, "dial OK!\n");
strncpy(ScriptBuffer, VarLoginScript, sizeof ScriptBuffer - 1);
if ((excode = DoChat(ScriptBuffer)) > 0) {
VarAltPhone = NULL;
if (VarTerm)
fprintf(VarTerm, "login OK!\n");
return EX_DONE;
} else if (excode == -1)
excode = EX_SIG;
else {
LogPrintf(LogWARN, "DialModem: login failed.\n");
excode = EX_NOLOGIN;
}
ModemTimeout(NULL); /* Dummy call to check modem status */
} else if (excode == -1)
excode = EX_SIG;
else {
LogPrintf(LogWARN, "DialModem: dial failed.\n");
excode = EX_NODIAL;
}
HangupModem(0);
return (excode);
}
int
ShowModemStatus(struct cmdargs const *arg)
{
const char *dev;
#ifdef TIOCOUTQ
int nb;
#endif
if (!VarTerm)
return 1;
dev = *VarDevice ? VarDevice : "network";
fprintf(VarTerm, "device: %s speed: ", dev);
if (DEV_IS_SYNC)
fprintf(VarTerm, "sync\n");
else
fprintf(VarTerm, "%d\n", VarSpeed);
switch (VarParity & CSIZE) {
case CS7:
fprintf(VarTerm, "cs7, ");
break;
case CS8:
fprintf(VarTerm, "cs8, ");
break;
}
if (VarParity & PARENB) {
if (VarParity & PARODD)
fprintf(VarTerm, "odd parity, ");
else
fprintf(VarTerm, "even parity, ");
} else
fprintf(VarTerm, "no parity, ");
fprintf(VarTerm, "CTS/RTS %s.\n", (VarCtsRts ? "on" : "off"));
if (LogIsKept(LogDEBUG))
fprintf(VarTerm, "fd = %d, modem control = %o\n", modem, mbits);
fprintf(VarTerm, "connect count: %d\n", connect_count);
#ifdef TIOCOUTQ
if (modem >= 0)
if (ioctl(modem, TIOCOUTQ, &nb) >= 0)
fprintf(VarTerm, "outq: %d\n", nb);
else
fprintf(VarTerm, "outq: ioctl probe failed: %s\n", strerror(errno));
#endif
fprintf(VarTerm, "outqlen: %d\n", ModemQlen());
fprintf(VarTerm, "DialScript = %s\n", VarDialScript);
fprintf(VarTerm, "LoginScript = %s\n", VarLoginScript);
fprintf(VarTerm, "PhoneNumber(s) = %s\n", VarPhoneList);
fprintf(VarTerm, "\n");
throughput_disp(&throughput, VarTerm);
return 0;
}

41
usr.sbin/ppp/modem.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: modem.h,v 1.15 1998/01/10 01:55:11 brian Exp $
*
* TODO:
*/
extern int RawModem(void);
extern void WriteModem(int, const char *, int);
extern void ModemStartOutput(int);
extern int OpenModem(void);
extern int ModemSpeed(void);
extern int ModemQlen(void);
extern int DialModem(void);
extern speed_t IntToSpeed(int);
extern void ModemTimeout(void *v);
extern void DownConnection(void);
extern void ModemOutput(int, struct mbuf *);
extern int ChangeParity(const char *);
extern void HangupModem(int);
extern int ShowModemStatus(struct cmdargs const *);
extern void Enqueue(struct mqueue *, struct mbuf *);
extern struct mbuf *Dequeue(struct mqueue *);
extern void SequenceQueues(void);
extern void ModemAddInOctets(int);
extern void ModemAddOutOctets(int);

397
usr.sbin/ppp/os.c Normal file
View File

@ -0,0 +1,397 @@
/*
* PPP OS Layer Interface Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: os.c,v 1.41 1998/01/19 02:59:33 brian Exp $
*
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "id.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "ipcp.h"
#include "os.h"
#include "loadalias.h"
#include "vars.h"
#include "arp.h"
#include "systems.h"
#include "route.h"
#include "lcp.h"
#include "ccp.h"
char *IfDevName;
static struct ifaliasreq ifra;
static struct ifreq ifrq;
static struct in_addr oldmine, oldhis;
static int linkup;
enum set_method { SET_UP, SET_DOWN, SET_TRY };
static int
SetIpDevice(struct in_addr myaddr,
struct in_addr hisaddr,
struct in_addr netmask,
enum set_method how)
{
struct sockaddr_in *sock_in;
int s;
u_long mask, addr;
s = ID0socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno));
return (-1);
}
if (how == SET_DOWN) {
if (Enabled(ConfProxy))
cifproxyarp(s, oldhis);
if (oldmine.s_addr == 0 && oldhis.s_addr == 0) {
close(s);
return (0);
}
memset(&ifra.ifra_addr, '\0', sizeof ifra.ifra_addr);
memset(&ifra.ifra_broadaddr, '\0', sizeof ifra.ifra_broadaddr);
memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCDIFADDR): %s\n",
strerror(errno));
close(s);
return (-1);
}
oldmine.s_addr = oldhis.s_addr = 0;
} else {
/* If given addresses are alreay set, then ignore this request */
if (oldmine.s_addr == myaddr.s_addr && oldhis.s_addr == hisaddr.s_addr) {
close(s);
return (0);
}
/*
* If different address has been set, then delete it first.
*/
if (oldmine.s_addr || oldhis.s_addr) {
memset(&ifra.ifra_addr, '\0', sizeof ifra.ifra_addr);
memset(&ifra.ifra_broadaddr, '\0', sizeof ifra.ifra_broadaddr);
memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCDIFADDR): %s\n",
strerror(errno));
close(s);
return (-1);
}
}
/* Set interface address */
sock_in = (struct sockaddr_in *) & (ifra.ifra_addr);
sock_in->sin_family = AF_INET;
sock_in->sin_addr = myaddr;
sock_in->sin_len = sizeof *sock_in;
/* Set destination address */
sock_in = (struct sockaddr_in *) & (ifra.ifra_broadaddr);
sock_in->sin_family = AF_INET;
sock_in->sin_addr = hisaddr;
sock_in->sin_len = sizeof *sock_in;
addr = ntohl(myaddr.s_addr);
if (IN_CLASSA(addr))
mask = IN_CLASSA_NET;
else if (IN_CLASSB(addr))
mask = IN_CLASSB_NET;
else
mask = IN_CLASSC_NET;
/*
* if subnet mask is given, use it instead of class mask.
*/
if (netmask.s_addr && (ntohl(netmask.s_addr) & mask) == mask)
mask = ntohl(netmask.s_addr);
sock_in = (struct sockaddr_in *) & (ifra.ifra_mask);
sock_in->sin_family = AF_INET;
sock_in->sin_addr.s_addr = htonl(mask);
sock_in->sin_len = sizeof *sock_in;
if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) {
if (how != SET_TRY)
LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCAIFADDR): %s\n",
strerror(errno));
close(s);
return (-1);
}
oldhis.s_addr = hisaddr.s_addr;
oldmine.s_addr = myaddr.s_addr;
if (Enabled(ConfProxy))
sifproxyarp(s, hisaddr);
}
close(s);
return (0);
}
int
CleanInterface(const char *name)
{
int s;
s = ID0socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno));
return (-1);
}
strncpy(ifrq.ifr_name, name, sizeof ifrq.ifr_name - 1);
ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
while (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0) {
memset(&ifra.ifra_mask, '\0', sizeof ifra.ifra_mask);
ifra.ifra_addr = ifrq.ifr_addr;
if (ID0ioctl(s, SIOCGIFDSTADDR, &ifrq) < 0) {
if (ifra.ifra_addr.sa_family == AF_INET)
LogPrintf(LogERROR, "tun_configure: Can't get dst for %s on %s !\n",
inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
name);
return 0;
}
ifra.ifra_broadaddr = ifrq.ifr_dstaddr;
if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) {
if (ifra.ifra_addr.sa_family == AF_INET)
LogPrintf(LogERROR, "tun_configure: Can't delete %s address on %s !\n",
inet_ntoa(((struct sockaddr_in *)&ifra.ifra_addr)->sin_addr),
name);
return 0;
}
}
return 1;
}
int
OsTrySetIpaddress(struct in_addr myaddr, struct in_addr hisaddr)
{
return (SetIpDevice(myaddr, hisaddr, ifnetmask, SET_TRY));
}
int
OsSetIpaddress(struct in_addr myaddr, struct in_addr hisaddr)
{
return (SetIpDevice(myaddr, hisaddr, ifnetmask, SET_UP));
}
static struct in_addr peer_addr;
void
OsLinkup()
{
char *s;
if (linkup == 0) {
reconnectState = RECON_UNKNOWN;
if (mode & MODE_BACKGROUND && BGFiledes[1] != -1) {
char c = EX_NORMAL;
if (write(BGFiledes[1], &c, 1) == 1)
LogPrintf(LogPHASE, "Parent notified of success.\n");
else
LogPrintf(LogPHASE, "Failed to notify parent of success.\n");
close(BGFiledes[1]);
BGFiledes[1] = -1;
}
peer_addr = IpcpInfo.his_ipaddr;
s = (char *) inet_ntoa(peer_addr);
if (LogIsKept(LogLINK))
LogPrintf(LogLINK, "OsLinkup: %s\n", s);
else
LogPrintf(LogLCP, "OsLinkup: %s\n", s);
if (SelectSystem(inet_ntoa(IpcpInfo.want_ipaddr), LINKUPFILE) < 0) {
if (GetLabel()) {
if (SelectSystem(GetLabel(), LINKUPFILE) < 0)
SelectSystem("MYADDR", LINKUPFILE);
} else
SelectSystem("MYADDR", LINKUPFILE);
}
linkup = 1;
}
}
int
OsLinkIsUp()
{
return linkup;
}
void
OsLinkdown()
{
char *s;
int Level;
if (linkup) {
s = (char *) inet_ntoa(peer_addr);
Level = LogIsKept(LogLINK) ? LogLINK : LogIPCP;
LogPrintf(Level, "OsLinkdown: %s\n", s);
FsmDown(&IpcpFsm); /* IPCP must come down */
FsmDown(&CcpFsm); /* CCP must come down */
linkup = 0;
if (SelectSystem(s, LINKDOWNFILE) < 0) {
if (GetLabel()) {
if (SelectSystem(GetLabel(), LINKDOWNFILE) < 0)
SelectSystem("MYADDR", LINKDOWNFILE);
} else
SelectSystem("MYADDR", LINKDOWNFILE);
}
}
}
int
OsInterfaceDown(int final)
{
struct in_addr zeroaddr;
int s;
OsLinkdown();
if (!final && (mode & MODE_DAEMON)) /* We still want interface alive */
return (0);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
LogPrintf(LogERROR, "OsInterfaceDown: socket: %s\n", strerror(errno));
return (-1);
}
ifrq.ifr_flags &= ~IFF_UP;
if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
LogPrintf(LogERROR, "OsInterfaceDown: ioctl(SIOCSIFFLAGS): %s\n",
strerror(errno));
close(s);
return (-1);
}
zeroaddr.s_addr = 0;
SetIpDevice(zeroaddr, zeroaddr, zeroaddr, SET_DOWN);
close(s);
return (0);
}
/*
* Open tunnel device and returns its descriptor
*/
#define MAX_TUN 256
/* MAX_TUN is set at an arbitrarily large value *
* as the loop aborts when it reaches the first *
* 'Device not configured' (ENXIO), or the third *
* 'No such file or directory' (ENOENT) error. */
int
OpenTunnel(int *ptun)
{
int s;
char ifname[IFNAMSIZ];
static char devname[14]; /* sufficient room for "/dev/tun65535" */
unsigned unit, enoentcount = 0;
int err;
err = ENOENT;
for (unit = 0; unit <= MAX_TUN; unit++) {
snprintf(devname, sizeof devname, "/dev/tun%d", unit);
tun_out = ID0open(devname, O_RDWR);
if (tun_out >= 0)
break;
if (errno == ENXIO) {
unit = MAX_TUN;
err = errno;
} else if (errno == ENOENT) {
enoentcount++;
if (enoentcount > 2)
unit = MAX_TUN;
} else
err = errno;
}
if (unit > MAX_TUN) {
if (VarTerm)
fprintf(VarTerm, "No tunnel device is available (%s).\n", strerror(err));
return -1;
}
*ptun = unit;
LogSetTun(unit);
/*
* At first, name the interface.
*/
strncpy(ifname, devname + 5, IFNAMSIZ - 1);
memset(&ifra, '\0', sizeof ifra);
memset(&ifrq, '\0', sizeof ifrq);
strncpy(ifrq.ifr_name, ifname, IFNAMSIZ - 1);
strncpy(ifra.ifra_name, ifname, IFNAMSIZ - 1);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
LogPrintf(LogERROR, "OpenTunnel: socket(): %s\n", strerror(errno));
return (-1);
}
/*
* Now, bring up the interface.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCGIFFLAGS): %s\n",
strerror(errno));
close(s);
return (-1);
}
ifrq.ifr_flags |= IFF_UP;
if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
LogPrintf(LogERROR, "OpenTunnel: ioctl(SIOCSIFFLAGS): %s\n",
strerror(errno));
close(s);
return (-1);
}
tun_in = tun_out;
IfDevName = devname + 5;
if (GetIfIndex(IfDevName) < 0) {
LogPrintf(LogERROR, "OpenTunnel: Can't find ifindex.\n");
close(s);
return (-1);
}
if (VarTerm)
fprintf(VarTerm, "Using interface: %s\n", IfDevName);
LogPrintf(LogPHASE, "Using interface: %s\n", IfDevName);
close(s);
return (0);
}

32
usr.sbin/ppp/os.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: os.h,v 1.13 1997/12/13 02:37:30 brian Exp $
*
* TODO:
*/
extern char *IfDevName;
extern int OsSetIpaddress(struct in_addr, struct in_addr);
extern int OsTrySetIpaddress(struct in_addr, struct in_addr);
extern int OsInterfaceDown(int);
extern int OpenTunnel(int *);
extern void OsLinkup(void);
extern int OsLinkIsUp(void);
extern void OsLinkdown(void);
extern int CleanInterface(const char *);

216
usr.sbin/ppp/pap.c Normal file
View File

@ -0,0 +1,216 @@
/*
* PPP PAP Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993-94, Internet Initiative Japan, Inc.
* All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: pap.c,v 1.19 1997/11/22 03:37:43 brian Exp $
*
* TODO:
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef __OpenBSD__
#include <util.h>
#else
#include <libutil.h>
#endif
#include <utmp.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "lcp.h"
#include "pap.h"
#include "loadalias.h"
#include "vars.h"
#include "hdlc.h"
#include "lcpproto.h"
#include "phase.h"
#include "auth.h"
static const char *papcodes[] = { "???", "REQUEST", "ACK", "NAK" };
static void
SendPapChallenge(int papid)
{
struct fsmheader lh;
struct mbuf *bp;
u_char *cp;
int namelen, keylen, plen;
namelen = strlen(VarAuthName);
keylen = strlen(VarAuthKey);
plen = namelen + keylen + 2;
LogPrintf(LogDEBUG, "SendPapChallenge: namelen = %d, keylen = %d\n",
namelen, keylen);
if (LogIsKept(LogDEBUG))
LogPrintf(LogPHASE, "PAP: %s (%s)\n", VarAuthName, VarAuthKey);
else
LogPrintf(LogPHASE, "PAP: %s\n", VarAuthName);
lh.code = PAP_REQUEST;
lh.id = papid;
lh.length = htons(plen + sizeof(struct fsmheader));
bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
*cp++ = namelen;
memcpy(cp, VarAuthName, namelen);
cp += namelen;
*cp++ = keylen;
memcpy(cp, VarAuthKey, keylen);
HdlcOutput(PRI_LINK, PROTO_PAP, bp);
}
struct authinfo AuthPapInfo = {
SendPapChallenge,
};
static void
SendPapCode(int id, int code, const char *message)
{
struct fsmheader lh;
struct mbuf *bp;
u_char *cp;
int plen, mlen;
lh.code = code;
lh.id = id;
mlen = strlen(message);
plen = mlen + 1;
lh.length = htons(plen + sizeof(struct fsmheader));
bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
*cp++ = mlen;
memcpy(cp, message, mlen);
LogPrintf(LogPHASE, "PapOutput: %s\n", papcodes[code]);
HdlcOutput(PRI_LINK, PROTO_PAP, bp);
}
/*
* Validate given username and passwrd against with secret table
*/
static int
PapValidate(u_char * name, u_char * key)
{
int nlen, klen;
nlen = *name++;
klen = *key;
*key++ = 0;
key[klen] = 0;
LogPrintf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
name, nlen, key, klen);
#ifndef NOPASSWDAUTH
if (Enabled(ConfPasswdAuth)) {
struct passwd *pwd;
int result;
LogPrintf(LogLCP, "Using PasswdAuth\n");
result = (pwd = getpwnam(name)) &&
!strcmp(crypt(key, pwd->pw_passwd), pwd->pw_passwd);
endpwent();
return result;
}
#endif
return (AuthValidate(SECRETFILE, name, key));
}
void
PapInput(struct mbuf * bp)
{
int len = plength(bp);
struct fsmheader *php;
struct lcpstate *lcp = &LcpInfo;
u_char *cp;
if (len >= sizeof(struct fsmheader)) {
php = (struct fsmheader *) MBUF_CTOP(bp);
if (len >= ntohs(php->length)) {
if (php->code < PAP_REQUEST || php->code > PAP_NAK)
php->code = 0;
LogPrintf(LogPHASE, "PapInput: %s\n", papcodes[php->code]);
switch (php->code) {
case PAP_REQUEST:
cp = (u_char *) (php + 1);
if (PapValidate(cp, cp + *cp + 1)) {
SendPapCode(php->id, PAP_ACK, "Greetings!!");
lcp->auth_ineed = 0;
if (lcp->auth_iwait == 0) {
if ((mode & MODE_DIRECT) && isatty(modem) && Enabled(ConfUtmp))
if (Utmp)
LogPrintf(LogERROR, "Oops, already logged in on %s\n",
VarBaseDevice);
else {
struct utmp ut;
memset(&ut, 0, sizeof ut);
time(&ut.ut_time);
strncpy(ut.ut_name, cp+1, sizeof ut.ut_name - 1);
strncpy(ut.ut_line, VarBaseDevice, sizeof ut.ut_line - 1);
if (logout(ut.ut_line))
logwtmp(ut.ut_line, "", "");
login(&ut);
Utmp = 1;
}
NewPhase(PHASE_NETWORK);
}
} else {
SendPapCode(php->id, PAP_NAK, "Login incorrect");
reconnect(RECON_FALSE);
LcpClose();
}
break;
case PAP_ACK:
StopAuthTimer(&AuthPapInfo);
cp = (u_char *) (php + 1);
len = *cp++;
cp[len] = 0;
LogPrintf(LogPHASE, "Received PAP_ACK (%s)\n", cp);
if (lcp->auth_iwait == PROTO_PAP) {
lcp->auth_iwait = 0;
if (lcp->auth_ineed == 0)
NewPhase(PHASE_NETWORK);
}
break;
case PAP_NAK:
StopAuthTimer(&AuthPapInfo);
cp = (u_char *) (php + 1);
len = *cp++;
cp[len] = 0;
LogPrintf(LogPHASE, "Received PAP_NAK (%s)\n", cp);
reconnect(RECON_FALSE);
LcpClose();
break;
}
}
}
pfree(bp);
}

29
usr.sbin/ppp/pap.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: pap.h,v 1.4 1997/10/26 01:03:29 brian Exp $
*
* TODO:
*/
#define PAP_REQUEST 1
#define PAP_ACK 2
#define PAP_NAK 3
extern struct authinfo AuthPapInfo;
extern void PapInput(struct mbuf *);

43
usr.sbin/ppp/pathnames.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 1989 The Regents of the University of California.
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* $Id: pathnames.h,v 1.7 1997/09/10 02:20:33 brian Exp $
*
* @(#)pathnames.h 5.2 (Berkeley) 6/1/90
*/
#if defined(__FreeBSD__) || defined(__OpenBSD__)
#define _PATH_PPP "/etc/ppp"
#else
#define _PATH_PPP "/etc"
#endif

105
usr.sbin/ppp/phase.c Normal file
View File

@ -0,0 +1,105 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "lcp.h"
#include "lcpproto.h"
#include "timer.h"
#include "auth.h"
#include "pap.h"
#include "chap.h"
#include "defs.h"
#include "ipcp.h"
#include "ccp.h"
#include "main.h"
#include "loadalias.h"
#include "vars.h"
#include "phase.h"
int phase = 0; /* Curent phase */
static const char *PhaseNames[] = {
"Dead", "Establish", "Authenticate", "Network", "Terminate"
};
static const char *
Auth2Nam(u_short auth)
{
switch (auth) {
case PROTO_PAP:
return "PAP";
case PROTO_CHAP:
return "CHAP";
case 0:
return "none";
}
return "unknown";
}
void
NewPhase(int new)
{
struct lcpstate *lcp = &LcpInfo;
phase = new;
LogPrintf(LogPHASE, "NewPhase: %s\n", PhaseNames[phase]);
switch (phase) {
case PHASE_AUTHENTICATE:
lcp->auth_ineed = lcp->want_auth;
lcp->auth_iwait = lcp->his_auth;
if (lcp->his_auth || lcp->want_auth) {
LogPrintf(LogPHASE, " his = %s, mine = %s\n",
Auth2Nam(lcp->his_auth), Auth2Nam(lcp->want_auth));
if (lcp->his_auth == PROTO_PAP)
StartAuthChallenge(&AuthPapInfo);
if (lcp->want_auth == PROTO_CHAP)
StartAuthChallenge(&AuthChapInfo);
} else
NewPhase(PHASE_NETWORK);
break;
case PHASE_NETWORK:
IpcpUp();
IpcpOpen();
CcpUp();
CcpOpen();
break;
case PHASE_DEAD:
if (mode & MODE_DIRECT)
Cleanup(EX_DEAD);
if (mode & MODE_BACKGROUND && reconnectState != RECON_TRUE)
Cleanup(EX_DEAD);
break;
}
}

31
usr.sbin/ppp/phase.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: phase.h,v 1.8 1997/10/26 01:03:32 brian Exp $
*
* TODO:
*/
#define PHASE_DEAD 0 /* Link is dead */
#define PHASE_ESTABLISH 1 /* Establishing link */
#define PHASE_AUTHENTICATE 2 /* Being authenticated */
#define PHASE_NETWORK 3
#define PHASE_TERMINATE 4 /* Terminating link */
extern int phase; /* Curent phase */
extern void NewPhase(int);

2597
usr.sbin/ppp/ppp.8 Normal file

File diff suppressed because it is too large Load Diff

342
usr.sbin/ppp/pred.c Normal file
View File

@ -0,0 +1,342 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* Ian Donaldson <iand@labtam.labtam.oz.au>
* Carsten Bormann <cabo@cs.tu-berlin.de>
* Dave Rand <dlr@bungi.com>/<dave_rand@novell.com>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: pred.c,v 1.19 1997/12/21 12:11:08 brian Exp $
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "loadalias.h"
#include "vars.h"
#include "timer.h"
#include "fsm.h"
#include "hdlc.h"
#include "lcpproto.h"
#include "lcp.h"
#include "ccp.h"
#include "pred.h"
/* The following hash code is the heart of the algorithm:
* It builds a sliding hash sum of the previous 3-and-a-bit characters
* which will be used to index the guess table.
* A better hash function would result in additional compression,
* at the expense of time.
*/
#define IHASH(x) do {iHash = (iHash << 4) ^ (x);} while(0)
#define OHASH(x) do {oHash = (oHash << 4) ^ (x);} while(0)
#define GUESS_TABLE_SIZE 65536
static unsigned short int iHash, oHash;
static unsigned char *InputGuessTable;
static unsigned char *OutputGuessTable;
static int
compress(u_char * source, u_char * dest, int len)
{
int i, bitmask;
unsigned char *flagdest, flags, *orgdest;
orgdest = dest;
while (len) {
flagdest = dest++;
flags = 0; /* All guess wrong initially */
for (bitmask = 1, i = 0; i < 8 && len; i++, bitmask <<= 1) {
if (OutputGuessTable[oHash] == *source) {
flags |= bitmask; /* Guess was right - don't output */
} else {
OutputGuessTable[oHash] = *source;
*dest++ = *source; /* Guess wrong, output char */
}
OHASH(*source++);
len--;
}
*flagdest = flags;
}
return (dest - orgdest);
}
static void
SyncTable(u_char * source, u_char * dest, int len)
{
while (len--) {
if (InputGuessTable[iHash] != *source) {
InputGuessTable[iHash] = *source;
}
IHASH(*dest++ = *source++);
}
}
static int
decompress(u_char * source, u_char * dest, int len)
{
int i, bitmask;
unsigned char flags, *orgdest;
orgdest = dest;
while (len) {
flags = *source++;
len--;
for (i = 0, bitmask = 1; i < 8; i++, bitmask <<= 1) {
if (flags & bitmask) {
*dest = InputGuessTable[iHash]; /* Guess correct */
} else {
if (!len)
break; /* we seem to be really done -- cabo */
InputGuessTable[iHash] = *source; /* Guess wrong */
*dest = *source++; /* Read from source */
len--;
}
IHASH(*dest++);
}
}
return (dest - orgdest);
}
static void
Pred1TermInput(void)
{
if (InputGuessTable != NULL) {
free(InputGuessTable);
InputGuessTable = NULL;
}
}
static void
Pred1TermOutput(void)
{
if (OutputGuessTable != NULL) {
free(OutputGuessTable);
OutputGuessTable = NULL;
}
}
static void
Pred1ResetInput(void)
{
iHash = 0;
memset(InputGuessTable, '\0', GUESS_TABLE_SIZE);
LogPrintf(LogCCP, "Predictor1: Input channel reset\n");
}
static void
Pred1ResetOutput(void)
{
oHash = 0;
memset(OutputGuessTable, '\0', GUESS_TABLE_SIZE);
LogPrintf(LogCCP, "Predictor1: Output channel reset\n");
}
static int
Pred1InitInput(void)
{
if (InputGuessTable == NULL)
if ((InputGuessTable = malloc(GUESS_TABLE_SIZE)) == NULL)
return 0;
Pred1ResetInput();
return 1;
}
static int
Pred1InitOutput(void)
{
if (OutputGuessTable == NULL)
if ((OutputGuessTable = malloc(GUESS_TABLE_SIZE)) == NULL)
return 0;
Pred1ResetOutput();
return 1;
}
static int
Pred1Output(int pri, u_short proto, struct mbuf * bp)
{
struct mbuf *mwp;
u_char *cp, *wp, *hp;
int orglen, len;
u_char bufp[MAX_MTU + 2];
u_short fcs;
orglen = plength(bp) + 2; /* add count of proto */
mwp = mballoc((orglen + 2) / 8 * 9 + 12, MB_HDLCOUT);
hp = wp = MBUF_CTOP(mwp);
cp = bufp;
*wp++ = *cp++ = orglen >> 8;
*wp++ = *cp++ = orglen & 0377;
*cp++ = proto >> 8;
*cp++ = proto & 0377;
mbread(bp, cp, orglen - 2);
fcs = HdlcFcs(INITFCS, bufp, 2 + orglen);
fcs = ~fcs;
len = compress(bufp + 2, wp, orglen);
LogPrintf(LogDEBUG, "Pred1Output: orglen (%d) --> len (%d)\n", orglen, len);
CcpInfo.uncompout += orglen;
if (len < orglen) {
*hp |= 0x80;
wp += len;
CcpInfo.compout += len;
} else {
memcpy(wp, bufp + 2, orglen);
wp += orglen;
CcpInfo.compout += orglen;
}
*wp++ = fcs & 0377;
*wp++ = fcs >> 8;
mwp->cnt = wp - MBUF_CTOP(mwp);
HdlcOutput(PRI_NORMAL, PROTO_COMPD, mwp);
return 1;
}
static struct mbuf *
Pred1Input(u_short *proto, struct mbuf *bp)
{
u_char *cp, *pp;
int len, olen, len1;
struct mbuf *wp;
u_char *bufp;
u_short fcs;
wp = mballoc(MAX_MTU + 2, MB_IPIN);
cp = MBUF_CTOP(bp);
olen = plength(bp);
pp = bufp = MBUF_CTOP(wp);
*pp++ = *cp & 0177;
len = *cp++ << 8;
*pp++ = *cp;
len += *cp++;
CcpInfo.uncompin += len & 0x7fff;
if (len & 0x8000) {
len1 = decompress(cp, pp, olen - 4);
CcpInfo.compin += olen;
len &= 0x7fff;
if (len != len1) { /* Error is detected. Send reset request */
LogPrintf(LogCCP, "Pred1: Length error\n");
CcpSendResetReq(&CcpFsm);
pfree(bp);
pfree(wp);
return NULL;
}
cp += olen - 4;
pp += len1;
} else {
CcpInfo.compin += len;
SyncTable(cp, pp, len);
cp += len;
pp += len;
}
*pp++ = *cp++; /* CRC */
*pp++ = *cp++;
fcs = HdlcFcs(INITFCS, bufp, wp->cnt = pp - bufp);
if (fcs != GOODFCS)
LogPrintf(LogDEBUG, "Pred1Input: fcs = 0x%04x (%s), len = 0x%x,"
" olen = 0x%x\n", fcs, (fcs == GOODFCS) ? "good" : "bad",
len, olen);
if (fcs == GOODFCS) {
wp->offset += 2; /* skip length */
wp->cnt -= 4; /* skip length & CRC */
pp = MBUF_CTOP(wp);
*proto = *pp++;
if (*proto & 1) {
wp->offset++;
wp->cnt--;
} else {
wp->offset += 2;
wp->cnt -= 2;
*proto = (*proto << 8) | *pp++;
}
pfree(bp);
return wp;
} else {
LogDumpBp(LogHDLC, "Bad FCS", wp);
CcpSendResetReq(&CcpFsm);
pfree(wp);
}
pfree(bp);
return NULL;
}
static void
Pred1DictSetup(u_short proto, struct mbuf * bp)
{
}
static const char *
Pred1DispOpts(struct lcp_opt *o)
{
return NULL;
}
static void
Pred1GetOpts(struct lcp_opt *o)
{
o->id = TY_PRED1;
o->len = 2;
}
static int
Pred1SetOpts(struct lcp_opt *o)
{
if (o->id != TY_PRED1 || o->len != 2) {
Pred1GetOpts(o);
return MODE_NAK;
}
return MODE_ACK;
}
const struct ccp_algorithm Pred1Algorithm = {
TY_PRED1,
ConfPred1,
Pred1DispOpts,
{
Pred1GetOpts,
Pred1SetOpts,
Pred1InitInput,
Pred1TermInput,
Pred1ResetInput,
Pred1Input,
Pred1DictSetup
},
{
Pred1GetOpts,
Pred1SetOpts,
Pred1InitOutput,
Pred1TermOutput,
Pred1ResetOutput,
Pred1Output
},
};

23
usr.sbin/ppp/pred.h Normal file
View File

@ -0,0 +1,23 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: pred.h,v 1.6 1997/10/26 01:03:35 brian Exp $
*
* TODO:
*/
extern const struct ccp_algorithm Pred1Algorithm;

577
usr.sbin/ppp/route.c Normal file
View File

@ -0,0 +1,577 @@
/*
* PPP Routing related Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: route.c,v 1.41 1998/01/19 02:59:33 brian Exp $
*
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if_dl.h>
#include <errno.h>
#include <machine/endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
#include "defs.h"
#include "vars.h"
#include "id.h"
#include "os.h"
#include "ipcp.h"
#include "iplist.h"
#include "route.h"
static int IfIndex;
struct rtmsg {
struct rt_msghdr m_rtm;
char m_space[64];
};
static int seqno;
void
OsSetRoute(int cmd,
struct in_addr dst,
struct in_addr gateway,
struct in_addr mask,
int bang)
{
struct rtmsg rtmes;
int s, nb, wb;
char *cp;
const char *cmdstr;
struct sockaddr_in rtdata;
if (bang)
cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!");
else
cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
s = ID0socket(PF_ROUTE, SOCK_RAW, 0);
if (s < 0) {
LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno));
return;
}
memset(&rtmes, '\0', sizeof rtmes);
rtmes.m_rtm.rtm_version = RTM_VERSION;
rtmes.m_rtm.rtm_type = cmd;
rtmes.m_rtm.rtm_addrs = RTA_DST;
rtmes.m_rtm.rtm_seq = ++seqno;
rtmes.m_rtm.rtm_pid = getpid();
rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
memset(&rtdata, '\0', sizeof rtdata);
rtdata.sin_len = 16;
rtdata.sin_family = AF_INET;
rtdata.sin_port = 0;
rtdata.sin_addr = dst;
cp = rtmes.m_space;
memcpy(cp, &rtdata, 16);
cp += 16;
if (cmd == RTM_ADD)
if (gateway.s_addr == INADDR_ANY) {
/* Add a route through the interface */
struct sockaddr_dl dl;
const char *iname;
int ilen;
iname = Index2Nam(IfIndex);
ilen = strlen(iname);
dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen;
dl.sdl_family = AF_LINK;
dl.sdl_index = IfIndex;
dl.sdl_type = 0;
dl.sdl_nlen = ilen;
dl.sdl_alen = 0;
dl.sdl_slen = 0;
strncpy(dl.sdl_data, iname, sizeof dl.sdl_data);
memcpy(cp, &dl, dl.sdl_len);
cp += dl.sdl_len;
rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
} else {
rtdata.sin_addr = gateway;
memcpy(cp, &rtdata, 16);
cp += 16;
rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
}
if (dst.s_addr == INADDR_ANY)
mask.s_addr = INADDR_ANY;
if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) {
rtdata.sin_addr = mask;
memcpy(cp, &rtdata, 16);
cp += 16;
rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
}
nb = cp - (char *) &rtmes;
rtmes.m_rtm.rtm_msglen = nb;
wb = ID0write(s, &rtmes, nb);
if (wb < 0) {
LogPrintf(LogTCPIP, "OsSetRoute failure:\n");
LogPrintf(LogTCPIP, "OsSetRoute: Cmd = %s\n", cmd);
LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst));
LogPrintf(LogTCPIP, "OsSetRoute: Gateway = %s\n", inet_ntoa(gateway));
LogPrintf(LogTCPIP, "OsSetRoute: Mask = %s\n", inet_ntoa(mask));
failed:
if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST ||
(rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST)))
if (!bang)
LogPrintf(LogWARN, "Add route failed: %s already exists\n",
inet_ntoa(dst));
else {
rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE;
if ((wb = ID0write(s, &rtmes, nb)) < 0)
goto failed;
}
else if (cmd == RTM_DELETE &&
(rtmes.m_rtm.rtm_errno == ESRCH ||
(rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) {
if (!bang)
LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n",
inet_ntoa(dst));
} else if (rtmes.m_rtm.rtm_errno == 0)
LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr,
inet_ntoa(dst), strerror(errno));
else
LogPrintf(LogWARN, "%s route failed: %s: %s\n",
cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
}
LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n",
wb, cmdstr, dst.s_addr, gateway.s_addr);
close(s);
}
static void
p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width)
{
char buf[29];
struct sockaddr_in *ihost = (struct sockaddr_in *)phost;
struct sockaddr_in *mask = (struct sockaddr_in *)pmask;
struct sockaddr_dl *dl = (struct sockaddr_dl *)phost;
switch (phost->sa_family) {
case AF_INET:
if (!phost)
buf[0] = '\0';
else if (ihost->sin_addr.s_addr == INADDR_ANY)
strcpy(buf, "default");
else if (!mask)
strcpy(buf, inet_ntoa(ihost->sin_addr));
else {
u_int msk = ntohl(mask->sin_addr.s_addr);
u_int tst;
int bits;
int len;
struct sockaddr_in net;
for (tst = 1, bits=32; tst; tst <<= 1, bits--)
if (msk & tst)
break;
for (tst <<=1; tst; tst <<= 1)
if (!(msk & tst))
break;
net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr;
strcpy(buf, inet_ntoa(net.sin_addr));
for (len = strlen(buf); len > 3; buf[len-=2] = '\0')
if (strcmp(buf+len-2, ".0"))
break;
if (tst) /* non-contiguous :-( */
sprintf(buf+strlen(buf),"&0x%08x", msk);
else
sprintf(buf+strlen(buf), "/%d", bits);
}
break;
case AF_LINK:
if (dl->sdl_nlen)
snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data);
else if (dl->sdl_alen)
if (dl->sdl_type == IFT_ETHER)
if (dl->sdl_alen < sizeof buf / 3) {
int f;
u_char *MAC;
MAC = (u_char *)dl->sdl_data + dl->sdl_nlen;
for (f = 0; f < dl->sdl_alen; f++)
sprintf(buf+f*3, "%02x:", MAC[f]);
buf[f*3-1] = '\0';
} else
strcpy(buf, "??:??:??:??:??:??");
else
sprintf(buf, "<IFT type %d>", dl->sdl_type);
else if (dl->sdl_slen)
sprintf(buf, "<slen %d?>", dl->sdl_slen);
else
sprintf(buf, "link#%d", dl->sdl_index);
break;
default:
sprintf(buf, "<AF type %d>", phost->sa_family);
break;
}
fprintf(VarTerm, "%-*s ", width-1, buf);
}
static struct bits {
u_long b_mask;
char b_val;
} bits[] = {
{ RTF_UP, 'U' },
{ RTF_GATEWAY, 'G' },
{ RTF_HOST, 'H' },
{ RTF_REJECT, 'R' },
{ RTF_DYNAMIC, 'D' },
{ RTF_MODIFIED, 'M' },
{ RTF_DONE, 'd' },
{ RTF_CLONING, 'C' },
{ RTF_XRESOLVE, 'X' },
{ RTF_LLINFO, 'L' },
{ RTF_STATIC, 'S' },
{ RTF_PROTO1, '1' },
{ RTF_PROTO2, '2' },
{ RTF_BLACKHOLE, 'B' },
#ifdef RTF_WASCLONED
{ RTF_WASCLONED, 'W' },
#endif
#ifdef RTF_PRCLONING
{ RTF_PRCLONING, 'c' },
#endif
#ifdef RTF_PROTO3
{ RTF_PROTO3, '3' },
#endif
#ifdef RTF_BROADCAST
{ RTF_BROADCAST, 'b' },
#endif
{ 0, '\0' }
};
#ifndef RTF_WASCLONED
#define RTF_WASCLONED (0)
#endif
static void
p_flags(u_long f, int max)
{
if (VarTerm) {
char name[33], *flags;
register struct bits *p = bits;
if (max > sizeof name - 1)
max = sizeof name - 1;
for (flags = name; p->b_mask && flags - name < max; p++)
if (p->b_mask & f)
*flags++ = p->b_val;
*flags = '\0';
fprintf(VarTerm, "%-*.*s", max, max, name);
}
}
const char *
Index2Nam(int idx)
{
static char **ifs;
static int nifs, debug_done;
if (!nifs) {
int mib[6], have, had;
size_t needed;
char *buf, *ptr, *end;
struct sockaddr_dl *dl;
struct if_msghdr *ifm;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno));
return "???";
}
if ((buf = malloc(needed)) == NULL)
return "???";
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
free(buf);
return "???";
}
end = buf + needed;
have = 0;
for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
ifm = (struct if_msghdr *)ptr;
dl = (struct sockaddr_dl *)(ifm + 1);
if (ifm->ifm_index > 0) {
if (ifm->ifm_index > have) {
had = have;
have = ifm->ifm_index + 5;
if (had)
ifs = (char **)realloc(ifs, sizeof(char *) * have);
else
ifs = (char **)malloc(sizeof(char *) * have);
if (!ifs) {
LogPrintf(LogDEBUG, "Index2Nam: %s\n", strerror(errno));
nifs = 0;
return "???";
}
memset(ifs + had, '\0', sizeof(char *) * (have - had));
}
if (ifs[ifm->ifm_index-1] == NULL) {
ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1);
memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen);
ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0';
if (nifs < ifm->ifm_index)
nifs = ifm->ifm_index;
}
} else if (LogIsKept(LogDEBUG))
LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n",
ifm->ifm_index);
}
free(buf);
}
if (LogIsKept(LogDEBUG) && !debug_done) {
int f;
LogPrintf(LogDEBUG, "Found the following interfaces:\n");
for (f = 0; f < nifs; f++)
if (ifs[f] != NULL)
LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]);
debug_done = 1;
}
if (idx < 1 || idx > nifs || ifs[idx-1] == NULL)
return "???";
return ifs[idx-1];
}
int
ShowRoute(struct cmdargs const *arg)
{
struct rt_msghdr *rtm;
struct sockaddr *sa_dst, *sa_gw, *sa_mask;
char *sp, *ep, *cp, *wp;
size_t needed;
int mib[6];
if (!VarTerm)
return 1;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno));
return (1);
}
if (needed < 0)
return (1);
sp = malloc(needed);
if (sp == NULL)
return (1);
if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno));
free(sp);
return (1);
}
ep = sp + needed;
fprintf(VarTerm, "%-20s%-20sFlags Netif\n", "Destination", "Gateway");
for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *) cp;
wp = (char *)(rtm+1);
if (rtm->rtm_addrs & RTA_DST) {
sa_dst = (struct sockaddr *)wp;
wp += sa_dst->sa_len;
} else
sa_dst = NULL;
if (rtm->rtm_addrs & RTA_GATEWAY) {
sa_gw = (struct sockaddr *)wp;
wp += sa_gw->sa_len;
} else
sa_gw = NULL;
if (rtm->rtm_addrs & RTA_NETMASK) {
sa_mask = (struct sockaddr *)wp;
wp += sa_mask->sa_len;
} else
sa_mask = NULL;
p_sockaddr(sa_dst, sa_mask, 20);
p_sockaddr(sa_gw, NULL, 20);
p_flags(rtm->rtm_flags, 6);
fprintf(VarTerm, " %s\n", Index2Nam(rtm->rtm_index));
}
free(sp);
return 0;
}
/*
* Delete routes associated with our interface
*/
void
DeleteIfRoutes(int all)
{
struct rt_msghdr *rtm;
struct sockaddr *sa;
struct in_addr sa_dst, sa_none;
int pass;
size_t needed;
char *sp, *cp, *ep;
int mib[6];
LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex);
sa_none.s_addr = INADDR_ANY;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n",
strerror(errno));
return;
}
if (needed < 0)
return;
sp = malloc(needed);
if (sp == NULL)
return;
if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n",
strerror(errno));
free(sp);
return;
}
ep = sp + needed;
for (pass = 0; pass < 2; pass++) {
/*
* We do 2 passes. The first deletes all cloned routes. The second
* deletes all non-cloned routes. This is necessary to avoid
* potential errors from trying to delete route X after route Y where
* route X was cloned from route Y (which is no longer there).
*/
if (RTF_WASCLONED == 0 && pass == 0)
/* So we can't tell ! */
continue;
for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *) cp;
sa = (struct sockaddr *) (rtm + 1);
LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s),"
" flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index,
Index2Nam(rtm->rtm_index), rtm->rtm_flags,
inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY &&
rtm->rtm_index == IfIndex &&
(all || (rtm->rtm_flags & RTF_GATEWAY))) {
sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
sa = (struct sockaddr *)((char *)sa + sa->sa_len);
if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) {
if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
(pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass);
OsSetRoute(RTM_DELETE, sa_dst, sa_none, sa_none, 0);
} else
LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass);
} else
LogPrintf(LogDEBUG,
"DeleteIfRoutes: Can't remove routes of %d family !\n",
sa->sa_family);
}
}
}
free(sp);
}
int
GetIfIndex(char *name)
{
int idx;
const char *got;
idx = 1;
while (strcmp(got = Index2Nam(idx), "???"))
if (!strcmp(got, name))
return IfIndex = idx;
else
idx++;
return -1;
}
struct in_addr
ChooseHisAddr(const struct in_addr gw)
{
struct in_addr try;
int f;
for (f = 0; f < DefHisChoice.nItems; f++) {
try = iplist_next(&DefHisChoice);
LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n",
f, inet_ntoa(try));
if (OsTrySetIpaddress(gw, try) == 0) {
LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n",
inet_ntoa(try));
break;
}
}
if (f == DefHisChoice.nItems) {
LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
try.s_addr = INADDR_ANY;
}
return try;
}

29
usr.sbin/ppp/route.h Normal file
View File

@ -0,0 +1,29 @@
/*
* User Process PPP
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: route.h,v 1.9 1997/12/30 02:45:48 brian Exp $
*
*/
extern int GetIfIndex(char *);
extern int ShowRoute(struct cmdargs const *);
extern void OsSetRoute(int, struct in_addr, struct in_addr, struct in_addr,int);
extern void DeleteIfRoutes(int);
extern struct in_addr ChooseHisAddr(const struct in_addr);
extern const char *Index2Nam(int);

169
usr.sbin/ppp/server.c Normal file
View File

@ -0,0 +1,169 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: server.c,v 1.15 1997/12/24 09:29:14 brian Exp $
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "loadalias.h"
#include "defs.h"
#include "vars.h"
#include "server.h"
#include "id.h"
int server = -1;
static struct sockaddr_un ifsun;
static char *rm;
int
ServerLocalOpen(const char *name, mode_t mask)
{
int s;
if (VarLocalAuth == LOCAL_DENY) {
LogPrintf(LogERROR, "Local: Can't open socket %s: No password "
"in ppp.secret\n", name);
return 1;
}
if (mode & MODE_INTER) {
LogPrintf(LogERROR, "Local: Can't open socket in interactive mode\n");
return 1;
}
memset(&ifsun, '\0', sizeof ifsun);
ifsun.sun_len = strlen(name);
if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
LogPrintf(LogERROR, "Local: %s: Path too long\n", name);
return 2;
}
ifsun.sun_family = AF_LOCAL;
strcpy(ifsun.sun_path, name);
s = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
if (s < 0) {
LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno));
return 3;
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
if (mask != (mode_t)-1)
mask = umask(mask);
if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) {
if (mask != (mode_t)-1)
umask(mask);
LogPrintf(LogERROR, "Local: bind: %s\n", strerror(errno));
if (errno == EADDRINUSE && VarTerm)
fprintf(VarTerm, "Wait for a while, then try again.\n");
close(s);
return 4;
}
if (mask != (mode_t)-1)
umask(mask);
if (listen(s, 5) != 0) {
LogPrintf(LogERROR, "Local: Unable to listen to socket - OS overload?\n");
close(s);
ID0unlink(name);
return 5;
}
ServerClose();
server = s;
rm = ifsun.sun_path;
LogPrintf(LogPHASE, "Listening at local socket %s.\n", name);
return 0;
}
int
ServerTcpOpen(int port)
{
struct sockaddr_in ifsin;
int s;
if (VarLocalAuth == LOCAL_DENY) {
LogPrintf(LogERROR, "Tcp: Can't open socket %d: No password "
"in ppp.secret\n", port);
return 6;
}
if (mode & MODE_INTER) {
LogPrintf(LogERROR, "Tcp: Can't open socket in interactive mode\n");
return 6;
}
s = ID0socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
return 7;
}
memset(&ifsin, '\0', sizeof ifsin);
ifsin.sin_family = AF_INET;
ifsin.sin_addr.s_addr = INADDR_ANY;
ifsin.sin_port = htons(port);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
LogPrintf(LogERROR, "Tcp: bind: %s\n", strerror(errno));
if (errno == EADDRINUSE && VarTerm)
fprintf(VarTerm, "Wait for a while, then try again.\n");
close(s);
return 8;
}
if (listen(s, 5) != 0) {
LogPrintf(LogERROR, "Tcp: Unable to listen to socket - OS overload?\n");
close(s);
return 9;
}
ServerClose();
server = s;
LogPrintf(LogPHASE, "Listening at port %d.\n", port);
return 0;
}
void
ServerClose()
{
if (server >= 0) {
close(server);
if (rm) {
ID0unlink(rm);
rm = 0;
}
}
server = -1;
}

33
usr.sbin/ppp/server.h Normal file
View File

@ -0,0 +1,33 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
extern int server;
extern int ServerLocalOpen(const char *, mode_t);
extern int ServerTcpOpen(int);
extern void ServerClose(void);

97
usr.sbin/ppp/sig.c Normal file
View File

@ -0,0 +1,97 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
#include <sys/types.h>
#include <signal.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "sig.h"
static caused[NSIG]; /* An array of pending signals */
static sig_type handler[NSIG]; /* all start at SIG_DFL */
/* Record a signal in the "caused" array */
static void
signal_recorder(int sig)
{
caused[sig - 1]++;
}
/*
* Set up signal_recorder, and record handler as the function to ultimately
* call in handle_signal()
*/
sig_type
pending_signal(int sig, sig_type fn)
{
sig_type Result;
if (sig <= 0 || sig > NSIG) {
/* Oops - we must be a bit out of date (too many sigs ?) */
LogPrintf(LogALERT, "Eeek! %s:%s: I must be out of date!\n",
__FILE__, __LINE__);
return signal(sig, fn);
}
Result = handler[sig - 1];
if (fn == SIG_DFL || fn == SIG_IGN) {
signal(sig, fn);
handler[sig - 1] = (sig_type) 0;
} else {
handler[sig - 1] = fn;
signal(sig, signal_recorder);
}
caused[sig - 1] = 0;
return Result;
}
/* Call the handlers for any pending signals */
void
handle_signals()
{
int sig;
int got;
do {
got = 0;
for (sig = 0; sig < NSIG; sig++)
if (caused[sig]) {
caused[sig]--;
got++;
(*handler[sig]) (sig + 1);
}
} while (got);
}

35
usr.sbin/ppp/sig.h Normal file
View File

@ -0,0 +1,35 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
typedef void (*sig_type)(int);
/* Call this instead of signal() */
extern sig_type pending_signal(int, sig_type);
/* Call this when you want things to *actually* happen */
extern void handle_signals(void);

587
usr.sbin/ppp/slcompress.c Normal file
View File

@ -0,0 +1,587 @@
/*
* 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.
*
* $Id: slcompress.c,v 1.14 1997/11/22 03:37:50 brian Exp $
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
#include <sys/param.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <string.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "slcompress.h"
#include "loadalias.h"
#include "vars.h"
static struct slstat {
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 */
} slstat;
#define INCR(counter) slstat.counter++;
void
sl_compress_init(struct slcompress * comp, int max_state)
{
register u_int i;
register struct cstate *tstate = comp->tstate;
memset(comp, '\0', 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 = SLF_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) {\
(f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
cp += 3; \
} else { \
(f) = htonl(ntohl(f) + (u_long)*cp++); \
} \
}
#define DECODES(f) { \
if (*cp == 0) {\
(f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
cp += 3; \
} else { \
(f) = htons(ntohs(f) + (u_long)*cp++); \
} \
}
#define DECODEU(f) { \
if (*cp == 0) {\
(f) = htons((cp[1] << 8) | cp[2]); \
cp += 3; \
} else { \
(f) = htons((u_long)*cp++); \
} \
}
u_char
sl_compress_tcp(struct mbuf * m,
struct ip * ip,
struct slcompress * comp,
int compress_cid)
{
register struct cstate *cs = comp->last_cs->cs_next;
register u_int hlen = ip->ip_hl;
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)) || m->cnt < 40) {
LogPrintf(LogDEBUG, "??? 1 ip_off = %x, cnt = %d\n",
ip->ip_off, m->cnt);
LogDumpBp(LogDEBUG, "", m);
return (TYPE_IP);
}
th = (struct tcphdr *) & ((int *) ip)[hlen];
if ((th->th_flags & (TH_SYN | TH_FIN | TH_RST | TH_ACK)) != TH_ACK) {
LogPrintf(LogDEBUG, "??? 2 th_flags = %x\n", th->th_flags);
LogDumpBp(LogDEBUG, "", m);
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(sls_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)[cs->cs_ip.ip_hl]) {
/*
* 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(sls_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)[cs->cs_ip.ip_hl])
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(sls_misses)
comp->last_cs = lcs;
#define THOFFSET(th) (th->th_off)
hlen += th->th_off;
hlen <<= 2;
if (hlen > m->cnt)
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 += th->th_off;
hlen <<= 2;
if (hlen > m->cnt)
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] ||
THOFFSET(th) != THOFFSET(oth) ||
(deltaS > 5 &&
memcmp(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
(THOFFSET(th) > 5 &&
memcmp(th + 1, oth + 1, (THOFFSET(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;
}
deltaS = (u_short) (ntohs(th->th_win) - ntohs(oth->th_win));
if (deltaS) {
ENCODE(deltaS);
changes |= NEW_W;
}
deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack);
if (deltaA) {
if (deltaA > 0xffff) {
goto uncompressed;
}
ENCODE(deltaA);
changes |= NEW_A;
}
deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq);
if (deltaS) {
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);
memcpy(&cs->cs_ip, 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;
/*
* Since fastq traffic can jump ahead of the background traffic, we don't
* know what order packets will go on the line. In this case, we always
* send a "new" connection id so the receiver state stays synchronized.
*/
if (comp->last_xmit == cs->cs_id && compress_cid) {
hlen -= deltaS + 3;
cp += hlen;
*cp++ = changes;
} else {
comp->last_xmit = cs->cs_id;
hlen -= deltaS + 4;
cp += hlen;
*cp++ = changes | NEW_C;
*cp++ = cs->cs_id;
}
m->cnt -= hlen;
m->offset += hlen;
*cp++ = deltaA >> 8;
*cp++ = deltaA;
memcpy(cp, new_seq, deltaS);
INCR(sls_compressed)
return (TYPE_COMPRESSED_TCP);
/*
* Update connection state cs & send uncompressed packet ('uncompressed'
* means a regular ip/tcp packet but with the 'conversation id' we hope to
* use on future compressed packets in the protocol field).
*/
uncompressed:
memcpy(&cs->cs_ip, ip, hlen);
ip->ip_p = cs->cs_id;
comp->last_xmit = cs->cs_id;
return (TYPE_UNCOMPRESSED_TCP);
}
int
sl_uncompress_tcp(u_char ** bufp,
int len,
u_int type,
struct slcompress * comp)
{
register u_char *cp;
register u_int hlen, changes;
register struct tcphdr *th;
register struct cstate *cs;
register struct ip *ip;
switch (type) {
case TYPE_UNCOMPRESSED_TCP:
ip = (struct ip *) * bufp;
if (ip->ip_p >= MAX_STATES)
goto bad;
cs = &comp->rstate[comp->last_recv = ip->ip_p];
comp->flags &= ~SLF_TOSS;
ip->ip_p = IPPROTO_TCP;
/*
* Calculate the size of the TCP/IP header and make sure that we don't
* overflow the space we have available for it.
*/
hlen = ip->ip_hl << 2;
if (hlen + sizeof(struct tcphdr) > len)
goto bad;
th = (struct tcphdr *) & ((char *) ip)[hlen];
hlen += THOFFSET(th) << 2;
if (hlen > MAX_HDR)
goto bad;
memcpy(&cs->cs_ip, ip, hlen);
cs->cs_ip.ip_sum = 0;
cs->cs_hlen = hlen;
INCR(sls_uncompressedin)
return (len);
default:
goto bad;
case TYPE_COMPRESSED_TCP:
break;
}
/* We've got a compressed packet. */
INCR(sls_compressedin)
cp = *bufp;
changes = *cp++;
LogPrintf(LogDEBUG, "compressed: changes = %02x\n", changes);
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 || comp->last_recv == 255)
goto bad;
comp->flags &= ~SLF_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 & SLF_TOSS) {
INCR(sls_tossed)
return (0);
}
}
cs = &comp->rstate[comp->last_recv];
hlen = cs->cs_ip.ip_hl << 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_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
th->th_ack = htonl(ntohl(th->th_ack) + i);
th->th_seq = htonl(ntohl(th->th_seq) + i);
}
break;
case SPECIAL_D:
th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len)
- cs->cs_hlen);
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) {
LogPrintf(LogDEBUG, "NEW_S: %02x, %02x, %02x\n",
*cp, cp[1], cp[2]);
DECODEL(th->th_seq)
}
break;
}
if (changes & NEW_I) {
DECODES(cs->cs_ip.ip_id)
} else
cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
LogPrintf(LogDEBUG, "Uncompress: id = %04x, seq = %08x\n",
cs->cs_ip.ip_id, ntohl(th->th_seq));
/*
* At this point, cp points to the first byte of data in the packet. If
* we're not aligned on a 4-byte boundary, copy the data down so the ip &
* tcp headers will be aligned. Then back up cp by the tcp/ip header
* length to make room for the reconstructed header (we assume the packet
* we were handed has enough space to prepend 128 bytes of header). Adjust
* the length to account for the new header & fill in the IP total length.
*/
len -= (cp - *bufp);
if (len < 0)
/*
* we must have dropped some characters (crc should detect this but the
* old slip framing won't)
*/
goto bad;
#ifdef notdef
if ((int) cp & 3) {
if (len > 0)
(void) bcopy(cp, (caddr_t) ((int) cp & ~3), len);
cp = (u_char *) ((int) cp & ~3);
}
#endif
cp -= cs->cs_hlen;
len += cs->cs_hlen;
cs->cs_ip.ip_len = htons(len);
memcpy(cp, &cs->cs_ip, cs->cs_hlen);
*bufp = cp;
/* recompute the ip header checksum */
{
register u_short *bp = (u_short *) cp;
for (changes = 0; hlen > 0; hlen -= 2)
changes += *bp++;
changes = (changes & 0xffff) + (changes >> 16);
changes = (changes & 0xffff) + (changes >> 16);
((struct ip *) cp)->ip_sum = ~changes;
}
return (len);
bad:
comp->flags |= SLF_TOSS;
INCR(sls_errorin)
return (0);
}
int
ReportCompress(struct cmdargs const *arg)
{
if (!VarTerm)
return 1;
fprintf(VarTerm, "Out: %d (compress) / %d (total)",
slstat.sls_compressed, slstat.sls_packets);
fprintf(VarTerm, " %d (miss) / %d (search)\n",
slstat.sls_misses, slstat.sls_searches);
fprintf(VarTerm, "In: %d (compress), %d (uncompress)",
slstat.sls_compressedin, slstat.sls_uncompressedin);
fprintf(VarTerm, " %d (error), %d (tossed)\n",
slstat.sls_errorin, slstat.sls_tossed);
return 0;
}

134
usr.sbin/ppp/slcompress.h Normal file
View File

@ -0,0 +1,134 @@
/*
* Definitions for tcp compression routines.
*
* $Header: /home/ncvs/src/usr.sbin/ppp/slcompress.h,v 1.9 1997/10/26 01:03:46 brian 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.
*
* $Id: slcompress.h,v 1.9 1997/10/26 01:03:46 brian Exp $
*
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
* - Initial distribution.
*/
#define MAX_STATES 16 /* must be > 2 and < 256 */
#define MAX_HDR 128 /* 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;
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 */
extern void sl_compress_init(struct slcompress *, int);
extern u_char sl_compress_tcp
(struct mbuf *, struct ip *, struct slcompress *, int);
extern int sl_uncompress_tcp(u_char **, int, u_int, struct slcompress *);
extern int ReportCompress(struct cmdargs const *);

366
usr.sbin/ppp/systems.c Normal file
View File

@ -0,0 +1,366 @@
/*
* System configuration routines
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: systems.c,v 1.34 1997/12/24 09:29:17 brian Exp $
*
* TODO:
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "id.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "loadalias.h"
#include "pathnames.h"
#include "vars.h"
#include "server.h"
#include "systems.h"
#define issep(ch) ((ch) == ' ' || (ch) == '\t')
FILE *
OpenSecret(const char *file)
{
FILE *fp;
char line[100];
snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file);
fp = ID0fopen(line, "r");
if (fp == NULL)
LogPrintf(LogWARN, "OpenSecret: Can't open %s.\n", line);
return (fp);
}
void
CloseSecret(FILE * fp)
{
fclose(fp);
}
/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */
static void
InterpretArg(char *from, char *to)
{
const char *env;
char *ptr, *startto, *endto;
int len;
startto = to;
endto = to + LINE_LEN - 1;
while(issep(*from))
from++;
if (*from == '~') {
ptr = strchr(++from, '/');
len = ptr ? ptr - from : strlen(from);
if (len == 0) {
if ((env = getenv("HOME")) == NULL)
env = _PATH_PPP;
strncpy(to, env, endto - to);
} else {
struct passwd *pwd;
strncpy(to, from, len);
to[len] = '\0';
pwd = getpwnam(to);
if (pwd)
strncpy(to, pwd->pw_dir, endto-to);
else
strncpy(to, _PATH_PPP, endto - to);
endpwent();
}
*endto = '\0';
to += strlen(to);
from += len;
}
while (to < endto && *from != '\0') {
if (*from == '$') {
if (from[1] == '$') {
*to = '\0'; /* For an empty var name below */
from += 2;
} else if (from[1] == '{') {
ptr = strchr(from+2, '}');
if (ptr) {
len = ptr - from - 2;
if (endto - to < len )
len = endto - to;
if (len) {
strncpy(to, from+2, len);
to[len] = '\0';
from = ptr+1;
} else {
*to++ = *from++;
continue;
}
} else {
*to++ = *from++;
continue;
}
} else {
ptr = to;
for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++)
*ptr++ = *from;
*ptr = '\0';
}
if (*to == '\0')
*to++ = '$';
else if ((env = getenv(to)) != NULL) {
strncpy(to, env, endto - to);
*endto = '\0';
to += strlen(to);
}
} else
*to++ = *from++;
}
while (to > startto) {
to--;
if (!issep(*to)) {
to++;
break;
}
}
*to = '\0';
}
#define CTRL_UNKNOWN (0)
#define CTRL_INCLUDE (1)
static int
DecodeCtrlCommand(char *line, char *arg)
{
if (!strncasecmp(line, "include", 7) && issep(line[7])) {
InterpretArg(line+8, arg);
return CTRL_INCLUDE;
}
return CTRL_UNKNOWN;
}
static int userok;
int
AllowUsers(struct cmdargs const *arg)
{
int f;
char *user;
userok = 0;
user = getlogin();
if (user && *user)
for (f = 0; f < arg->argc; f++)
if (!strcmp("*", arg->argv[f]) || !strcmp(user, arg->argv[f])) {
userok = 1;
break;
}
return 0;
}
static struct {
int mode;
const char *name;
} modes[] = {
{ MODE_INTER, "interactive" },
{ MODE_AUTO, "auto" },
{ MODE_DIRECT, "direct" },
{ MODE_DEDICATED, "dedicated" },
{ MODE_DDIAL, "ddial" },
{ MODE_BACKGROUND, "background" },
{ ~0, "*" },
{ 0, 0 }
};
static int modeok;
int
AllowModes(struct cmdargs const *arg)
{
int f;
int m;
int allowed;
allowed = 0;
for (f = 0; f < arg->argc; f++) {
for (m = 0; modes[m].mode; m++)
if (!strcasecmp(modes[m].name, arg->argv[f])) {
allowed |= modes[m].mode;
break;
}
if (modes[m].mode == 0)
LogPrintf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]);
}
modeok = (mode | allowed) == allowed ? 1 : 0;
return 0;
}
static int
ReadSystem(const char *name, const char *file, int doexec)
{
FILE *fp;
char *cp, *wp;
int n, len;
u_char olauth;
char line[LINE_LEN];
char filename[MAXPATHLEN];
int linenum;
int argc;
char **argv;
int allowcmd;
if (*file == '/')
snprintf(filename, sizeof filename, "%s", file);
else
snprintf(filename, sizeof filename, "%s/%s", _PATH_PPP, file);
fp = ID0fopen(filename, "r");
if (fp == NULL) {
LogPrintf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename);
return (-1);
}
LogPrintf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename);
linenum = 0;
while (fgets(line, sizeof line, fp)) {
linenum++;
cp = line;
switch (*cp) {
case '#': /* comment */
break;
case ' ':
case '\t':
break;
default:
wp = strpbrk(cp, ":\n");
if (wp == NULL) {
LogPrintf(LogWARN, "Bad rule in %s (line %d) - missing colon.\n",
filename, linenum);
ServerClose();
exit(1);
}
*wp = '\0';
if (*cp == '!') {
char arg[LINE_LEN];
switch (DecodeCtrlCommand(cp+1, arg)) {
case CTRL_INCLUDE:
LogPrintf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg);
n = ReadSystem(name, arg, doexec);
LogPrintf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg);
if (!n)
return 0; /* got it */
break;
default:
LogPrintf(LogWARN, "%s: %s: Invalid command\n", filename, cp);
break;
}
} else if (strcmp(cp, name) == 0) {
while (fgets(line, sizeof line, fp)) {
cp = line;
if (issep(*cp)) {
n = strspn(cp, " \t");
cp += n;
len = strlen(cp);
if (!len || *cp == '#')
continue;
if (cp[len-1] == '\n')
cp[--len] = '\0';
if (!len)
continue;
InterpretCommand(cp, len, &argc, &argv);
allowcmd = argc > 0 && !strcasecmp(*argv, "allow");
if ((!doexec && allowcmd) || (doexec && !allowcmd)) {
olauth = VarLocalAuth;
if (VarLocalAuth == LOCAL_NO_AUTH)
VarLocalAuth = LOCAL_AUTH;
RunCommand(argc, (char const *const *)argv, name);
VarLocalAuth = olauth;
}
} else if (*cp == '#' || *cp == '\n' || *cp == '\0') {
continue;
} else
break;
}
fclose(fp);
return (0);
}
break;
}
}
fclose(fp);
return -1;
}
int
ValidSystem(const char *name)
{
if (ID0realuid() == 0)
return userok = modeok = 1;
userok = 0;
modeok = 1;
ReadSystem("default", CONFFILE, 0);
if (name != NULL)
ReadSystem(name, CONFFILE, 0);
return userok && modeok;
}
int
SelectSystem(const char *name, const char *file)
{
userok = modeok = 1;
return ReadSystem(name, file, 1);
}
int
LoadCommand(struct cmdargs const *arg)
{
const char *name;
if (arg->argc > 0)
name = *arg->argv;
else
name = "default";
if (!ValidSystem(name)) {
LogPrintf(LogERROR, "%s: Label not allowed\n", name);
return 1;
} else if (SelectSystem(name, CONFFILE) < 0) {
LogPrintf(LogWARN, "%s: label not found.\n", name);
return -1;
} else
SetLabel(arg->argc ? name : NULL);
return 0;
}
int
SaveCommand(struct cmdargs const *arg)
{
LogPrintf(LogWARN, "save command is not implemented (yet).\n");
return 1;
}

31
usr.sbin/ppp/systems.h Normal file
View File

@ -0,0 +1,31 @@
/*
* User Process PPP
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: systems.h,v 1.9 1997/11/11 22:58:14 brian Exp $
*
*/
extern int SelectSystem(const char *, const char *);
extern int ValidSystem(const char *);
extern FILE *OpenSecret(const char *);
extern void CloseSecret(FILE *);
extern int AllowUsers(struct cmdargs const *);
extern int AllowModes(struct cmdargs const *);
extern int LoadCommand(struct cmdargs const *);
extern int SaveCommand(struct cmdargs const *);

151
usr.sbin/ppp/throughput.c Normal file
View File

@ -0,0 +1,151 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
#include <sys/param.h>
#include <stdio.h>
#include <time.h>
#include <netinet/in.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "timer.h"
#include "throughput.h"
#include "defs.h"
#include "loadalias.h"
#include "vars.h"
void
throughput_init(struct pppThroughput *t)
{
int f;
t->OctetsIn = t->OctetsOut = 0;
for (f = 0; f < SAMPLE_PERIOD; f++)
t->SampleOctets[f] = 0;
t->OctetsPerSecond = t->BestOctetsPerSecond = t->nSample = 0;
throughput_stop(t);
}
void
throughput_disp(struct pppThroughput *t, FILE *f)
{
int secs_up;
secs_up = t->uptime ? time(NULL) - t->uptime : 0;
fprintf(f, "Connect time: %d secs\n", secs_up);
if (secs_up == 0)
secs_up = 1;
fprintf(f, "%ld octets in, %ld octets out\n", t->OctetsIn, t->OctetsOut);
if (Enabled(ConfThroughput)) {
fprintf(f, " overall %5ld bytes/sec\n",
(t->OctetsIn+t->OctetsOut)/secs_up);
fprintf(f, " currently %5d bytes/sec\n", t->OctetsPerSecond);
fprintf(f, " peak %5d bytes/sec\n", t->BestOctetsPerSecond);
} else
fprintf(f, "Overall %ld bytes/sec\n", (t->OctetsIn+t->OctetsOut)/secs_up);
}
void
throughput_log(struct pppThroughput *t, int level, const char *title)
{
if (t->uptime) {
int secs_up;
secs_up = t->uptime ? time(NULL) - t->uptime : 0;
if (title)
LogPrintf(level, "%s: Connect time: %d secs: %ld octets in, %ld octets"
" out\n", title, secs_up, t->OctetsIn, t->OctetsOut);
else
LogPrintf(level, "Connect time: %d secs: %ld octets in, %ld octets out\n",
secs_up, t->OctetsIn, t->OctetsOut);
if (secs_up == 0)
secs_up = 1;
if (Enabled(ConfThroughput))
LogPrintf(level, " total %ld bytes/sec, peak %d bytes/sec\n",
(t->OctetsIn+t->OctetsOut)/secs_up, t->BestOctetsPerSecond);
else
LogPrintf(level, " total %ld bytes/sec\n",
(t->OctetsIn+t->OctetsOut)/secs_up);
}
}
static void
throughput_sampler(void *v)
{
struct pppThroughput *t = (struct pppThroughput *)v;
u_long old;
StopTimer(&t->Timer);
t->Timer.state = TIMER_STOPPED;
old = t->SampleOctets[t->nSample];
t->SampleOctets[t->nSample] = t->OctetsIn + t->OctetsOut;
t->OctetsPerSecond = (t->SampleOctets[t->nSample] - old) / SAMPLE_PERIOD;
if (t->BestOctetsPerSecond < t->OctetsPerSecond)
t->BestOctetsPerSecond = t->OctetsPerSecond;
if (++t->nSample == SAMPLE_PERIOD)
t->nSample = 0;
StartTimer(&t->Timer);
}
void
throughput_start(struct pppThroughput *t)
{
throughput_init(t);
time(&t->uptime);
if (Enabled(ConfThroughput)) {
t->Timer.state = TIMER_STOPPED;
t->Timer.load = SECTICKS;
t->Timer.func = throughput_sampler;
t->Timer.arg = t;
StartTimer(&t->Timer);
}
}
void
throughput_stop(struct pppThroughput *t)
{
if (Enabled(ConfThroughput))
StopTimer(&t->Timer);
}
void
throughput_addin(struct pppThroughput *t, int n)
{
t->OctetsIn += n;
}
void
throughput_addout(struct pppThroughput *t, int n)
{
t->OctetsOut += n;
}

48
usr.sbin/ppp/throughput.h Normal file
View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
#define SAMPLE_PERIOD 5
struct pppThroughput {
time_t uptime;
u_long OctetsIn;
u_long OctetsOut;
u_long SampleOctets[SAMPLE_PERIOD];
int OctetsPerSecond;
int BestOctetsPerSecond;
int nSample;
struct pppTimer Timer;
};
extern void throughput_init(struct pppThroughput *);
extern void throughput_disp(struct pppThroughput *, FILE *);
extern void throughput_log(struct pppThroughput *, int, const char *);
extern void throughput_start(struct pppThroughput *);
extern void throughput_stop(struct pppThroughput *);
extern void throughput_addin(struct pppThroughput *, int);
extern void throughput_addout(struct pppThroughput *, int);

289
usr.sbin/ppp/timer.c Normal file
View File

@ -0,0 +1,289 @@
/*
* PPP Timer Processing Module
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: timer.c,v 1.26 1997/12/29 22:23:52 brian Exp $
*
* TODO:
*/
#include <signal.h>
#ifdef SIGALRM
#include <errno.h>
#endif
#include <sys/time.h>
#include <unistd.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "sig.h"
#include "timer.h"
static struct pppTimer *TimerList = NULL;
static void StopTimerNoBlock(struct pppTimer *);
static void InitTimerService(void);
void
StopTimer(struct pppTimer * tp)
{
#ifdef SIGALRM
int omask;
omask = sigblock(sigmask(SIGALRM));
#endif
StopTimerNoBlock(tp);
#ifdef SIGALRM
sigsetmask(omask);
#endif
}
void
StartTimer(struct pppTimer * tp)
{
struct pppTimer *t, *pt;
u_long ticks = 0;
#ifdef SIGALRM
int omask;
omask = sigblock(sigmask(SIGALRM));
#endif
if (tp->state != TIMER_STOPPED) {
StopTimerNoBlock(tp);
}
if (tp->load == 0) {
LogPrintf(LogDEBUG, "timer %x has 0 load!\n", tp);
sigsetmask(omask);
return;
}
pt = NULL;
for (t = TimerList; t; t = t->next) {
LogPrintf(LogDEBUG, "StartTimer: %x(%d): ticks: %d, rest: %d\n",
t, t->state, ticks, t->rest);
if (ticks + t->rest >= tp->load)
break;
ticks += t->rest;
pt = t;
}
tp->state = TIMER_RUNNING;
tp->rest = tp->load - ticks;
LogPrintf(LogDEBUG, "StartTimer: Inserting %x before %x, rest = %d\n",
tp, t, tp->rest);
/* Insert given *tp just before *t */
tp->next = t;
if (pt) {
pt->next = tp;
} else {
InitTimerService();
TimerList = tp;
}
if (t)
t->rest -= tp->rest;
#ifdef SIGALRM
sigsetmask(omask);
#endif
}
static void
StopTimerNoBlock(struct pppTimer * tp)
{
struct pppTimer *t, *pt;
/*
* A Running Timer should be removing TimerList, But STOPPED/EXPIRED is
* already removing TimerList. So just marked as TIMER_STOPPED. Do not
* change tp->enext!! (Might be Called by expired proc)
*/
LogPrintf(LogDEBUG, "StopTimer: %x, next = %x state=%x\n",
tp, tp->next, tp->state);
if (tp->state != TIMER_RUNNING) {
tp->next = NULL;
tp->state = TIMER_STOPPED;
return;
}
pt = NULL;
for (t = TimerList; t != tp && t != NULL; t = t->next)
pt = t;
if (t) {
if (pt) {
pt->next = t->next;
} else {
TimerList = t->next;
if (TimerList == NULL) /* Last one ? */
TermTimerService(); /* Terminate Timer Service */
}
if (t->next)
t->next->rest += tp->rest;
} else
LogPrintf(LogERROR, "Oops, timer not found!!\n");
tp->next = NULL;
tp->state = TIMER_STOPPED;
}
static void
TimerService()
{
struct pppTimer *tp, *exp, *wt;
if (LogIsKept(LogDEBUG))
ShowTimers();
tp = TimerList;
if (tp) {
tp->rest--;
if (tp->rest == 0) {
/*
* Multiple timers may expires at once. Create list of expired timers.
*/
exp = NULL;
do {
tp->state = TIMER_EXPIRED;
wt = tp->next;
tp->enext = exp;
exp = tp;
LogPrintf(LogDEBUG, "TimerService: Add %x to exp\n", tp);
tp = wt;
} while (tp && (tp->rest == 0));
TimerList = tp;
if (TimerList == NULL) /* No timers ? */
TermTimerService(); /* Terminate Timer Service */
LogPrintf(LogDEBUG, "TimerService: next is %x(%d)\n",
TimerList, TimerList ? TimerList->rest : 0);
/*
* Process all expired timers.
*/
while (exp) {
#ifdef notdef
StopTimer(exp);
#endif
if (exp->func)
(*exp->func) (exp->arg);
/*
* Just Removing each item from expired list And exp->enext will be
* intialized at next expire in this funtion.
*/
exp = exp->enext;
}
}
}
}
void
ShowTimers()
{
struct pppTimer *pt;
LogPrintf(LogDEBUG, "---- Begin of Timer Service List---\n");
for (pt = TimerList; pt; pt = pt->next)
LogPrintf(LogDEBUG, "%x: load = %d, rest = %d, state =%x\n",
pt, pt->load, pt->rest, pt->state);
LogPrintf(LogDEBUG, "---- End of Timer Service List ---\n");
}
#ifdef SIGALRM
static void
nointr_dosleep(u_int sec, u_int usec)
{
struct timeval to, st, et;
gettimeofday(&st, NULL);
et.tv_sec = st.tv_sec + sec;
et.tv_usec = st.tv_usec + usec;
to.tv_sec = sec;
to.tv_usec = usec;
for (;;) {
if (select(0, NULL, NULL, NULL, &to) == 0 ||
errno != EINTR) {
break;
} else {
gettimeofday(&to, NULL);
if (to.tv_sec > et.tv_sec + 1 ||
(to.tv_sec == et.tv_sec + 1 && to.tv_usec > et.tv_usec) ||
to.tv_sec < st.tv_sec ||
(to.tv_sec == st.tv_sec && to.tv_usec < st.tv_usec)) {
LogPrintf(LogWARN, "Clock adjusted between %d and %d seconds "
"during sleep !\n",
to.tv_sec - st.tv_sec, sec + to.tv_sec - st.tv_sec);
st.tv_sec = to.tv_sec;
st.tv_usec = to.tv_usec;
et.tv_sec = st.tv_sec + sec;
et.tv_usec = st.tv_usec + usec;
to.tv_sec = sec;
to.tv_usec = usec;
} else if (to.tv_sec > et.tv_sec ||
(to.tv_sec == et.tv_sec && to.tv_usec >= et.tv_usec)) {
break;
} else {
to.tv_sec = et.tv_sec - to.tv_sec;
if (et.tv_usec < to.tv_usec) {
to.tv_sec--;
to.tv_usec = 1000000 + et.tv_usec - to.tv_usec;
} else
to.tv_usec = et.tv_usec - to.tv_usec;
}
}
}
}
void
nointr_sleep(u_int sec)
{
nointr_dosleep(sec, 0);
}
void
nointr_usleep(u_int usec)
{
nointr_dosleep(0, usec);
}
static void
InitTimerService()
{
struct itimerval itimer;
pending_signal(SIGALRM, (void (*) (int)) TimerService);
itimer.it_interval.tv_sec = itimer.it_value.tv_sec = 0;
itimer.it_interval.tv_usec = itimer.it_value.tv_usec = TICKUNIT;
if (setitimer(ITIMER_REAL, &itimer, NULL) == -1)
LogPrintf(LogERROR, "Unable to set itimer.\n");
}
void
TermTimerService(void)
{
struct itimerval itimer;
itimer.it_interval.tv_usec = itimer.it_interval.tv_sec = 0;
itimer.it_value.tv_usec = itimer.it_value.tv_sec = 0;
if (setitimer(ITIMER_REAL, &itimer, NULL) == -1)
LogPrintf(LogERROR, "Unable to set itimer.\n");
pending_signal(SIGALRM, SIG_IGN);
}
#endif

48
usr.sbin/ppp/timer.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: timer.h,v 1.4 1997/12/28 21:55:05 brian Exp $
*
* TODO:
*/
#define TICKUNIT 100000 /* Unit in usec */
#define SECTICKS (1000000/TICKUNIT)
struct pppTimer {
int state;
u_long rest; /* Ticks to expire */
u_long load; /* Initial load value */
void (*func)(void *); /* Function called when timer is expired */
void *arg; /* Argument passed to timeout function */
struct pppTimer *next; /* Link to next timer */
struct pppTimer *enext; /* Link to next expired timer */
};
#define TIMER_STOPPED 0
#define TIMER_RUNNING 1
#define TIMER_EXPIRED 2
extern void StartTimer(struct pppTimer *);
extern void StopTimer(struct pppTimer *);
extern void TermTimerService(void);
extern void ShowTimers(void);
#ifdef SIGALRM
extern void nointr_sleep(u_int);
extern void nointr_usleep(u_int);
#endif

66
usr.sbin/ppp/tun.c Normal file
View File

@ -0,0 +1,66 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: tun.c,v 1.5 1998/01/11 17:53:27 brian Exp $
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_tun.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "hdlc.h"
#include "defs.h"
#include "loadalias.h"
#include "vars.h"
#include "tun.h"
void
tun_configure(int mtu, int speed)
{
struct tuninfo info;
info.type = 23;
info.mtu = mtu;
if (VarPrefMTU != 0 && VarPrefMTU < mtu)
info.mtu = VarPrefMTU;
info.baudrate = speed;
#ifdef __OpenBSD__
info.flags = IFF_UP|IFF_POINTOPOINT;
#endif
if (ioctl(tun_out, TUNSIFINFO, &info) < 0)
LogPrintf(LogERROR, "tun_configure: ioctl(TUNSIFINFO): %s\n",
strerror(errno));
}

44
usr.sbin/ppp/tun.h Normal file
View File

@ -0,0 +1,44 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*/
struct tun_data {
#ifdef __OpenBSD__
struct tunnel_header head;
#endif
u_char data[MAX_MRU];
};
#ifdef __OpenBSD__
#define tun_fill_header(f,proto) do { (f).head.tun_af = (proto); } while (0)
#define tun_check_header(f,proto) ((f).head.tun_af == (proto))
#else
#define tun_fill_header(f,proto) do { } while (0)
#define tun_check_header(f,proto) (1)
#endif
extern void tun_configure(int, int);

192
usr.sbin/ppp/vars.c Normal file
View File

@ -0,0 +1,192 @@
/*
* PPP configuration variables
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: vars.c,v 1.44 1998/01/20 22:47:48 brian Exp $
*
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "defs.h"
#include "timer.h"
#include "fsm.h"
#include "hdlc.h"
#include "termios.h"
#include "loadalias.h"
#include "vars.h"
#include "auth.h"
char VarVersion[] = "PPP Version 1.65";
char VarLocalVersion[] = "$Date: 1998/01/20 22:47:48 $";
int Utmp = 0;
int ipKeepAlive = 0;
int reconnectState = RECON_UNKNOWN;
int reconnectCount = 0;
/*
* Order of conf option is important. See vars.h.
*/
struct confdesc pppConfs[] = {
{"acfcomp", CONF_ENABLE, CONF_ACCEPT},
{"chap", CONF_DISABLE, CONF_ACCEPT},
{"deflate", CONF_ENABLE, CONF_ACCEPT},
{"lqr", CONF_DISABLE, CONF_ACCEPT},
{"pap", CONF_DISABLE, CONF_ACCEPT},
{"pppd-deflate", CONF_DISABLE, CONF_DENY},
{"pred1", CONF_ENABLE, CONF_ACCEPT},
{"protocomp", CONF_ENABLE, CONF_ACCEPT},
{"vjcomp", CONF_ENABLE, CONF_ACCEPT},
{"msext", CONF_DISABLE, CONF_NONE},
{"passwdauth", CONF_DISABLE, CONF_NONE},
{"proxy", CONF_DISABLE, CONF_NONE},
{"throughput", CONF_DISABLE, CONF_NONE},
{"utmp", CONF_ENABLE, CONF_NONE},
{NULL},
};
struct pppvars pppVars = {
DEF_MRU, DEF_MTU, 0, MODEM_SPEED, CS8, MODEM_CTSRTS, 180, 30, 3,
RECONNECT_TIMER, RECONNECT_TRIES, REDIAL_PERIOD,
NEXT_REDIAL_PERIOD, 1, 1, MODEM_DEV, "", BASE_MODEM_DEV,
1, LOCAL_NO_AUTH, 0
};
int
DisplayCommand(struct cmdargs const *arg)
{
struct confdesc *vp;
if (!VarTerm)
return 1;
fprintf(VarTerm, "Current configuration option settings..\n\n");
fprintf(VarTerm, "Name\t\tMy Side\t\tHis Side\n");
fprintf(VarTerm, "----------------------------------------\n");
for (vp = pppConfs; vp->name; vp++)
fprintf(VarTerm, "%-10s\t%s\t\t%s\n", vp->name,
(vp->myside == CONF_ENABLE) ? "enable" :
(vp->myside == CONF_DISABLE ? "disable" : "N/A"),
(vp->hisside == CONF_ACCEPT) ? "accept" :
(vp->hisside == CONF_DENY ? "deny" : "N/A"));
return 0;
}
static int
ConfigCommand(struct cmdargs const *arg, int mine, int val)
{
struct confdesc *vp;
int err;
int narg = 0;
if (arg->argc < 1)
return -1;
err = 0;
do {
for (vp = pppConfs; vp->name; vp++)
if (strcasecmp(vp->name, arg->argv[narg]) == 0) {
if (mine) {
if (vp->myside == CONF_NONE) {
LogPrintf(LogWARN, "Config: %s cannot be enabled or disabled\n",
vp->name);
err++;
} else
vp->myside = val;
} else {
if (vp->hisside == CONF_NONE) {
LogPrintf(LogWARN, "Config: %s cannot be accepted or denied\n",
vp->name);
err++;
} else
vp->hisside = val;
}
break;
}
if (!vp->name) {
LogPrintf(LogWARN, "Config: %s: No such key word\n", arg->argv[narg]);
err++;
}
} while (++narg < arg->argc);
return err;
}
int
EnableCommand(struct cmdargs const *arg)
{
return ConfigCommand(arg, 1, CONF_ENABLE);
}
int
DisableCommand(struct cmdargs const *arg)
{
return ConfigCommand(arg, 1, CONF_DISABLE);
}
int
AcceptCommand(struct cmdargs const *arg)
{
return ConfigCommand(arg, 0, CONF_ACCEPT);
}
int
DenyCommand(struct cmdargs const *arg)
{
return ConfigCommand(arg, 0, CONF_DENY);
}
int
LocalAuthCommand(struct cmdargs const *arg)
{
const char *pass;
if (arg->argc == 0)
pass = "";
else if (arg->argc > 1)
return -1;
else
pass = *arg->argv;
if (VarHaveLocalAuthKey)
VarLocalAuth = strcmp(VarLocalAuthKey, pass) ? LOCAL_NO_AUTH : LOCAL_AUTH;
else
switch (LocalAuthValidate(SECRETFILE, VarShortHost, pass)) {
case INVALID:
VarLocalAuth = LOCAL_NO_AUTH;
break;
case VALID:
VarLocalAuth = LOCAL_AUTH;
break;
case NOT_FOUND:
VarLocalAuth = LOCAL_AUTH;
LogPrintf(LogWARN, "WARNING: No Entry for this system\n");
break;
default:
VarLocalAuth = LOCAL_NO_AUTH;
LogPrintf(LogERROR, "LocalAuthCommand: Ooops?\n");
return 1;
}
return 0;
}

205
usr.sbin/ppp/vars.h Normal file
View File

@ -0,0 +1,205 @@
/*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan. The name of the
* IIJ 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.
*
* $Id: vars.h,v 1.41 1998/01/20 22:47:48 brian Exp $
*
* TODO:
*/
struct confdesc {
const char *name;
int myside, hisside;
};
#define CONF_NONE -1
#define CONF_DISABLE 0
#define CONF_ENABLE 1
#define CONF_DENY 0
#define CONF_ACCEPT 1
#define ConfAcfcomp 0
#define ConfChap 1
#define ConfDeflate 2
#define ConfLqr 3
#define ConfPap 4
#define ConfPppdDeflate 5
#define ConfPred1 6
#define ConfProtocomp 7
#define ConfVjcomp 8
#define ConfMSExt 9
#define ConfPasswdAuth 10
#define ConfProxy 11
#define ConfThroughput 12
#define ConfUtmp 13
#define MAXCONFS 14
#define Enabled(x) (pppConfs[x].myside & CONF_ENABLE)
#define Acceptable(x) (pppConfs[x].hisside & CONF_ACCEPT)
extern struct confdesc pppConfs[MAXCONFS + 1];
struct pppvars {
u_short var_mru; /* Initial MRU value */
u_short pref_mtu; /* Preferred MTU value */
int var_accmap; /* Initial ACCMAP value */
int modem_speed; /* Current modem speed */
int modem_parity; /* Parity setting */
int modem_ctsrts; /* Use CTS/RTS on modem port? (boolean) */
int idle_timeout; /* Idle timeout value */
int lqr_timeout; /* LQR timeout value */
int retry_timeout; /* Retry timeout value */
int reconnect_timer; /* Timeout before reconnect on carrier loss */
int reconnect_tries; /* Attempt reconnect on carrier loss */
int redial_timeout; /* Redial timeout value */
int redial_next_timeout; /* Redial next timeout value */
int dial_tries; /* Dial attempts before giving up, 0 == inf */
int loopback; /* Turn around packets addressed to me */
char modem_devlist[LINE_LEN]; /* Comma-separated list of devices */
char modem_dev[40]; /* Name of device / host:port */
const char *base_modem_dev; /* Pointer to base of modem_dev */
int open_mode; /* Delay before first LCP REQ (-1 = passive) */
#define LOCAL_AUTH 0x01
#define LOCAL_NO_AUTH 0x02
#define LOCAL_DENY 0x03
u_char lauth; /* Local Authorized status */
FILE *termfp; /* The terminal */
#define DIALUP_REQ 0x01
#define DIALUP_DONE 0x02
char dial_script[SCRIPT_LEN]; /* Dial script */
char login_script[SCRIPT_LEN]; /* Login script */
char auth_key[50]; /* PAP/CHAP key */
char auth_name[50]; /* PAP/CHAP system name */
char local_auth_key[50]; /* Local auth passwd */
int have_local_auth_key; /* Local auth passwd specified ? */
#ifdef HAVE_DES
int use_MSChap; /* Use MSCHAP encryption */
#endif
char phone_numbers[200]; /* Telephone Numbers */
char phone_copy[200]; /* copy for strsep() */
char *next_phone; /* Next phone from the list */
char *alt_phone; /* Next phone from the list */
char shostname[MAXHOSTNAMELEN]; /* Local short Host Name */
char hangup_script[SCRIPT_LEN]; /* Hangup script before modem is closed */
struct aliasHandlers handler; /* Alias function pointers */
};
#define VarAccmap pppVars.var_accmap
#define VarMRU pppVars.var_mru
#define VarPrefMTU pppVars.pref_mtu
#define VarDevice pppVars.modem_dev
#define VarDeviceList pppVars.modem_devlist
#define VarBaseDevice pppVars.base_modem_dev
#define VarSpeed pppVars.modem_speed
#define VarParity pppVars.modem_parity
#define VarCtsRts pppVars.modem_ctsrts
#define VarOpenMode pppVars.open_mode
#define VarLocalAuth pppVars.lauth
#define VarDialScript pppVars.dial_script
#define VarHangupScript pppVars.hangup_script
#define VarLoginScript pppVars.login_script
#define VarIdleTimeout pppVars.idle_timeout
#define VarLqrTimeout pppVars.lqr_timeout
#define VarRetryTimeout pppVars.retry_timeout
#define VarAuthKey pppVars.auth_key
#define VarAuthName pppVars.auth_name
#define VarLocalAuthKey pppVars.local_auth_key
#define VarHaveLocalAuthKey pppVars.have_local_auth_key
#ifdef HAVE_DES
#define VarMSChap pppVars.use_MSChap
#endif
#define VarPhoneList pppVars.phone_numbers
#define VarPhoneCopy pppVars.phone_copy
#define VarNextPhone pppVars.next_phone
#define VarAltPhone pppVars.alt_phone
#define VarShortHost pppVars.shostname
#define VarReconnectTimer pppVars.reconnect_timer
#define VarReconnectTries pppVars.reconnect_tries
#define VarRedialTimeout pppVars.redial_timeout
#define VarRedialNextTimeout pppVars.redial_next_timeout
#define VarDialTries pppVars.dial_tries
#define VarLoopback pppVars.loopback
#define VarTerm pppVars.termfp
#define VarAliasHandlers pppVars.handler
#define VarPacketAliasGetFragment (*pppVars.handler.PacketAliasGetFragment)
#define VarPacketAliasGetFragment (*pppVars.handler.PacketAliasGetFragment)
#define VarPacketAliasInit (*pppVars.handler.PacketAliasInit)
#define VarPacketAliasIn (*pppVars.handler.PacketAliasIn)
#define VarPacketAliasOut (*pppVars.handler.PacketAliasOut)
#define VarPacketAliasRedirectAddr (*pppVars.handler.PacketAliasRedirectAddr)
#define VarPacketAliasRedirectPort (*pppVars.handler.PacketAliasRedirectPort)
#define VarPacketAliasSaveFragment (*pppVars.handler.PacketAliasSaveFragment)
#define VarPacketAliasSetAddress (*pppVars.handler.PacketAliasSetAddress)
#define VarPacketAliasSetMode (*pppVars.handler.PacketAliasSetMode)
#define VarPacketAliasFragmentIn (*pppVars.handler.PacketAliasFragmentIn)
#define DEV_IS_SYNC (VarSpeed == 0)
extern struct pppvars pppVars;
extern char VarVersion[];
extern char VarLocalVersion[];
extern int Utmp; /* Are we in /etc/utmp ? */
extern int ipKeepAlive;
extern int reconnectState;
extern int reconnectCount;
#define RECON_TRUE (1)
#define RECON_FALSE (2)
#define RECON_UNKNOWN (3)
#define RECON_ENVOKED (4)
#define reconnect(x) \
do \
if (reconnectState == RECON_UNKNOWN) { \
reconnectState = x; \
if (x == RECON_FALSE) \
reconnectCount = 0; \
} \
while(0)
/*
* This is the logic behind the reconnect variables:
* We have four reconnect "states". We start off not requiring anything
* from the reconnect code (reconnectState == RECON_UNKNOWN). If the
* line is brought down (via LcpClose() or LcpDown()), we have to decide
* whether to set to RECON_TRUE or RECON_FALSE. It's only here that we
* know the correct action. Once we've decided, we don't want that
* decision to be overridden (hence the above reconnect() macro) - If we
* call LcpClose, the ModemTimeout() still gets to "notice" that the line
* is down. When it "notice"s, it should only set RECON_TRUE if a decision
* hasn't already been made.
*
* In main.c, when we notice we have RECON_TRUE, we must only action
* it once. The fourth "state" is where we're bringing the line up,
* but if we call LcpClose for any reason (failed PAP/CHAP etc) we
* don't want to set to RECON_{TRUE,FALSE}.
*
* If we get a connection or give up dialing, we go back to RECON_UNKNOWN.
* If we get give up dialing or reconnecting or if we chose to down the
* connection, we set reconnectCount back to zero.
*
*/
extern int EnableCommand(struct cmdargs const *);
extern int DisableCommand(struct cmdargs const *);
extern int AcceptCommand(struct cmdargs const *);
extern int DenyCommand(struct cmdargs const *);
extern int LocalAuthCommand(struct cmdargs const *);
extern int DisplayCommand(struct cmdargs const *);

164
usr.sbin/ppp/vjcomp.c Normal file
View File

@ -0,0 +1,164 @@
/*
* Input/Output VJ Compressed packets
*
* Written by Toshiharu OHNO (tony-o@iij.ad.jp)
*
* Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
*
* 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 Internet Initiative Japan, Inc. The name of the
* IIJ 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.
*
* $Id: vjcomp.c,v 1.15 1998/01/11 17:50:46 brian Exp $
*
* TODO:
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <string.h>
#include "command.h"
#include "mbuf.h"
#include "log.h"
#include "timer.h"
#include "fsm.h"
#include "lcpproto.h"
#include "slcompress.h"
#include "hdlc.h"
#include "ipcp.h"
#include "vjcomp.h"
#define MAX_VJHEADER 16 /* Maximum size of compressed header */
static struct slcompress cslc;
void
VjInit(int max_state)
{
sl_compress_init(&cslc, max_state);
}
void
SendPppFrame(struct mbuf * bp)
{
int type;
u_short proto;
u_short cproto = IpcpInfo.his_compproto >> 16;
LogPrintf(LogDEBUG, "SendPppFrame: proto = %x\n", IpcpInfo.his_compproto);
if (((struct ip *) MBUF_CTOP(bp))->ip_p == IPPROTO_TCP
&& cproto == PROTO_VJCOMP) {
type = sl_compress_tcp(bp, (struct ip *)MBUF_CTOP(bp), &cslc,
IpcpInfo.his_compproto & 0xff);
LogPrintf(LogDEBUG, "SendPppFrame: type = %x\n", type);
switch (type) {
case TYPE_IP:
proto = PROTO_IP;
break;
case TYPE_UNCOMPRESSED_TCP:
proto = PROTO_VJUNCOMP;
break;
case TYPE_COMPRESSED_TCP:
proto = PROTO_VJCOMP;
break;
default:
LogPrintf(LogERROR, "Unknown frame type %x\n", type);
pfree(bp);
return;
}
} else
proto = PROTO_IP;
HdlcOutput(PRI_NORMAL, proto, bp);
}
static struct mbuf *
VjUncompressTcp(struct mbuf * bp, u_char type)
{
u_char *bufp;
int len, olen, rlen;
struct mbuf *nbp;
u_char work[MAX_HDR + MAX_VJHEADER]; /* enough to hold TCP/IP header */
olen = len = plength(bp);
if (type == TYPE_UNCOMPRESSED_TCP) {
/*
* Uncompressed packet does NOT change its size, so that we can use mbuf
* space for uncompression job.
*/
bufp = MBUF_CTOP(bp);
len = sl_uncompress_tcp(&bufp, len, type, &cslc);
if (len <= 0) {
pfree(bp);
bp = NULL;
}
return (bp);
}
/*
* Handle compressed packet. 1) Read upto MAX_VJHEADER bytes into work
* space. 2) Try to uncompress it. 3) Compute amount of necesary space. 4)
* Copy unread data info there.
*/
if (len > MAX_VJHEADER)
len = MAX_VJHEADER;
rlen = len;
bufp = work + MAX_HDR;
bp = mbread(bp, bufp, rlen);
len = sl_uncompress_tcp(&bufp, olen, type, &cslc);
if (len <= 0) {
pfree(bp);
return NULL;
}
len -= olen;
len += rlen;
nbp = mballoc(len, MB_VJCOMP);
memcpy(MBUF_CTOP(nbp), bufp, len);
nbp->next = bp;
return (nbp);
}
struct mbuf *
VjCompInput(struct mbuf * bp, int proto)
{
u_char type;
LogPrintf(LogDEBUG, "VjCompInput: proto %02x\n", proto);
LogDumpBp(LogDEBUG, "Raw packet info:", bp);
switch (proto) {
case PROTO_VJCOMP:
type = TYPE_COMPRESSED_TCP;
break;
case PROTO_VJUNCOMP:
type = TYPE_UNCOMPRESSED_TCP;
break;
default:
LogPrintf(LogERROR, "VjCompInput...???\n");
return (bp);
}
bp = VjUncompressTcp(bp, type);
return (bp);
}
const char *
vj2asc(u_int32_t val)
{
static char asc[50];
sprintf(asc, "%d VJ slots %s slot compression",
(int)((val>>8)&15)+1, val & 1 ? "with" : "without");
return asc;
}

32
usr.sbin/ppp/vjcomp.h Normal file
View File

@ -0,0 +1,32 @@
/*-
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: vjcomp.h,v 1.4 1997/12/21 12:11:10 brian Exp $
*/
extern void VjInit(int);
extern void SendPppFrame(struct mbuf *);
extern struct mbuf *VjCompInput(struct mbuf *, int);
extern const char *vj2asc(u_int32_t);