This commit was manufactured by cvs2svn to create branch 'MP'.
This commit is contained in:
commit
1ae349f52c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/MP/; revision=32861
320
etc/ppp/ppp.conf.sample
Normal file
320
etc/ppp/ppp.conf.sample
Normal 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
|
26
etc/ppp/ppp.linkdown.sample
Normal file
26
etc/ppp/ppp.linkdown.sample
Normal 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
55
etc/ppp/ppp.linkup.sample
Normal 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
23
etc/ppp/ppp.secret.sample
Normal 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
43
usr.sbin/ppp/Makefile
Normal 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
352
usr.sbin/ppp/README.alias
Normal 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
22
usr.sbin/ppp/README.devel
Normal 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
195
usr.sbin/ppp/alias_cmd.c
Normal 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
9
usr.sbin/ppp/alias_cmd.h
Normal 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
355
usr.sbin/ppp/arp.c
Normal 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
25
usr.sbin/ppp/arp.h
Normal 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
197
usr.sbin/ppp/async.c
Normal 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
32
usr.sbin/ppp/async.h
Normal 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
212
usr.sbin/ppp/auth.c
Normal 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
41
usr.sbin/ppp/auth.h
Normal 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
432
usr.sbin/ppp/ccp.c
Normal 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
92
usr.sbin/ppp/ccp.h
Normal 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
311
usr.sbin/ppp/chap.c
Normal 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
30
usr.sbin/ppp/chap.h
Normal 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
112
usr.sbin/ppp/chap_ms.c
Normal 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
31
usr.sbin/ppp/chap_ms.h
Normal 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
678
usr.sbin/ppp/chat.c
Normal 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
29
usr.sbin/ppp/chat.h
Normal 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
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
62
usr.sbin/ppp/command.h
Normal 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
617
usr.sbin/ppp/deflate.c
Normal 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
30
usr.sbin/ppp/deflate.h
Normal 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
116
usr.sbin/ppp/defs.c
Normal 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
95
usr.sbin/ppp/defs.h
Normal 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
499
usr.sbin/ppp/filter.c
Normal 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
87
usr.sbin/ppp/filter.h
Normal 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
820
usr.sbin/ppp/fsm.c
Normal 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
132
usr.sbin/ppp/fsm.h
Normal 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
576
usr.sbin/ppp/hdlc.c
Normal 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
66
usr.sbin/ppp/hdlc.h
Normal 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
177
usr.sbin/ppp/id.c
Normal 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
38
usr.sbin/ppp/id.h
Normal 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
537
usr.sbin/ppp/ip.c
Normal 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
31
usr.sbin/ppp/ip.h
Normal 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
710
usr.sbin/ppp/ipcp.c
Normal 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
83
usr.sbin/ppp/ipcp.h
Normal 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
224
usr.sbin/ppp/iplist.c
Normal 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
48
usr.sbin/ppp/iplist.h
Normal 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
835
usr.sbin/ppp/lcp.c
Normal 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
82
usr.sbin/ppp/lcp.h
Normal 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
39
usr.sbin/ppp/lcpproto.h
Normal 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
169
usr.sbin/ppp/loadalias.c
Normal 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
45
usr.sbin/ppp/loadalias.h
Normal 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
245
usr.sbin/ppp/log.c
Normal 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
68
usr.sbin/ppp/log.h
Normal 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
272
usr.sbin/ppp/lqr.c
Normal 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
64
usr.sbin/ppp/lqr.h
Normal 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
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
31
usr.sbin/ppp/main.h
Normal 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
175
usr.sbin/ppp/mbuf.c
Normal 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
60
usr.sbin/ppp/mbuf.h
Normal 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
947
usr.sbin/ppp/modem.c
Normal 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
41
usr.sbin/ppp/modem.h
Normal 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
397
usr.sbin/ppp/os.c
Normal 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
32
usr.sbin/ppp/os.h
Normal 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
216
usr.sbin/ppp/pap.c
Normal 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
29
usr.sbin/ppp/pap.h
Normal 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
43
usr.sbin/ppp/pathnames.h
Normal 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
105
usr.sbin/ppp/phase.c
Normal 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
31
usr.sbin/ppp/phase.h
Normal 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
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
342
usr.sbin/ppp/pred.c
Normal 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
23
usr.sbin/ppp/pred.h
Normal 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
577
usr.sbin/ppp/route.c
Normal 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
29
usr.sbin/ppp/route.h
Normal 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
169
usr.sbin/ppp/server.c
Normal 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
33
usr.sbin/ppp/server.h
Normal 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
97
usr.sbin/ppp/sig.c
Normal 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
35
usr.sbin/ppp/sig.h
Normal 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
587
usr.sbin/ppp/slcompress.c
Normal 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
134
usr.sbin/ppp/slcompress.h
Normal 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
366
usr.sbin/ppp/systems.c
Normal 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
31
usr.sbin/ppp/systems.h
Normal 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
151
usr.sbin/ppp/throughput.c
Normal 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
48
usr.sbin/ppp/throughput.h
Normal 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
289
usr.sbin/ppp/timer.c
Normal 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
48
usr.sbin/ppp/timer.h
Normal 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
66
usr.sbin/ppp/tun.c
Normal 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
44
usr.sbin/ppp/tun.h
Normal 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
192
usr.sbin/ppp/vars.c
Normal 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
205
usr.sbin/ppp/vars.h
Normal 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
164
usr.sbin/ppp/vjcomp.c
Normal 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
32
usr.sbin/ppp/vjcomp.h
Normal 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);
|
Loading…
Reference in New Issue
Block a user