diff options
author | ed <ed@FreeBSD.org> | 2009-04-05 22:08:18 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-04-05 22:08:18 +0000 |
commit | 36d960175a8cfcbccee2d24424dc7677bbf9954a (patch) | |
tree | 8a97b6bb04afecdfb70c99fe4302c043d6d240e0 /usr.sbin/pppd | |
parent | 18eefdb2b28b2ccc1394a40d490c6b1b0c80086d (diff) | |
download | FreeBSD-src-36d960175a8cfcbccee2d24424dc7677bbf9954a.zip FreeBSD-src-36d960175a8cfcbccee2d24424dc7677bbf9954a.tar.gz |
Remove if_ppp(4) and if_sl(4).
Not only did these two drivers depend on IFF_NEEDSGIANT, they were
broken 7 months ago during the MPSAFE TTY import. if_ppp(4) has been
replaced by ppp(8). There is no replacement for if_sl(4).
If we see regressions in for example the ports tree, we should just use
__FreeBSD_version 800045 to check whether if_ppp(4) and if_sl(4) are
present. Version 800045 is used to denote the import of MPSAFE TTY.
Discussed with: rwatson, but also rwatson's IFF_NEEDSGIANT emails on the
lists.
Diffstat (limited to 'usr.sbin/pppd')
35 files changed, 0 insertions, 22101 deletions
diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile deleted file mode 100644 index 2df0330..0000000 --- a/usr.sbin/pppd/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# $FreeBSD$ - -.include <bsd.own.mk> - -# I once used this extensively, but no longer have a modem. Feel free -# to ask me questions about it, but I disclaim ownership now. -Peter - -PROG= pppd -MAN= pppd.8 -SRCS= main.c magic.c fsm.c lcp.c ipcp.c ipxcp.c upap.c chap.c ccp.c \ - demand.c auth.c options.c sys-bsd.c -BINMODE=4550 -BINOWN= root -BINGRP= dialer - -CFLAGS+= -DHAVE_PATHS_H - -DPADD= ${LIBCRYPT} ${LIBUTIL} ${LIBMD} -LDADD= -lcrypt -lutil -lmd - -# Support SPX/IPX - not quite ready -#CFLAGS+= -DIPX_CHANGE -#SRCS+= ipxcp.c - -# Callback Control Protocol -CFLAGS+= -DCBCP_SUPPORT -SRCS+= cbcp.c - -# Filter support -CFLAGS+= -DPPP_FILTER -DPADD+= ${LIBPCAP} -LDADD+= -lpcap - -# MS-CHAP support. Requires the DES library. -.if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH) -CFLAGS+= -DCHAPMS -SRCS+= chap_ms.c -LDADD+= -lcrypto -DPADD+= ${LIBCRYPTO} -.endif - -.if ${MK_INET6_SUPPORT} != "no" -CFLAGS+=-DINET6 -SRCS+= eui64.c ipv6cp.c -.endif - -.if defined(RELEASE_CRUNCH) -# We must create these objects because crunchgen will link them, -# and we don't want any unused symbols to spoil the final link. -SRCS+= chap_ms.c -chap_ms.o: - >null_${.PREFIX}.c - cc -c -o ${.TARGET} null_${.PREFIX}.c -.endif - -.include <bsd.prog.mk> diff --git a/usr.sbin/pppd/RELNOTES b/usr.sbin/pppd/RELNOTES deleted file mode 100644 index 1c1e3922..0000000 --- a/usr.sbin/pppd/RELNOTES +++ /dev/null @@ -1,726 +0,0 @@ -# $FreeBSD$ - -This is the README file for ppp-2.3, a package which implements the -Point-to-Point Protocol (PPP) to provide Internet connections over -serial lines. - - -Introduction. -************* - -The Point-to-Point Protocol (PPP) provides a standard way to establish -a network connection over a serial link. At present, this package -supports IP and the protocols layered above IP, such as TCP and UDP. -The Linux port of this package also has support for IPX. - -This software consists of two parts: - -- Kernel code, which establishes a network interface and passes -packets between the serial port, the kernel networking code and the -PPP daemon (pppd). This code is implemented using STREAMS modules on -SunOS 4.x, Solaris 2.x, System V Release 4, and OSF/1, and as a -line discipline under Ultrix, NextStep, NetBSD, FreeBSD, and Linux. - -- The PPP daemon (pppd), which negotiates with the peer to establish -the link and sets up the ppp network interface. Pppd includes support -for authentication, so you can control which other systems may make a -PPP connection and what IP addresses they may use. - - -Installation. -************* - -The file SETUP contains general information about setting up your -system for using PPP. There is also a README file for each supported -system, which contains more specific details for installing PPP on -that system. The supported systems, and the corresponding README -files, are: - - Digital Unix (OSF/1) README.osf - Linux README.linux - NetBSD, FreeBSD README.bsd - NeXTStep README.next - Solaris 2 README.sol2 - SunOS 4.x README.sunos4 - System V Release 4 README.svr4 - Ultrix 4.x README.ultrix - -Unfortunately, AIX 4 is no longer supported, since I don't have a -maintainer for the AIX 4 port. If you want to volunteer, contact me. -The Ultrix port is untested, as I no longer have access to an Ultrix -box. - -In each case you start by running the ./configure script. This works -out which operating system you are using and creates symbolic links to -the appropriate makefiles. You then run `make' to compile the -user-level code, and (as root) `make install' to install the -user-level programs pppd, chat and pppstats. - -The procedures for installing the kernel code vary from system to -system. On some systems, the kernel code can be loaded into a running -kernel using a `modload' facility. On others, the kernel image has to -be recompiled and the system rebooted. See the README.* files for -details. - -N.B. Since 2.3.0, leaving the permitted IP addresses column of the -pap-secrets or chap-secrets file empty means that no addresses are -permitted. You need to put a "*" in that column to allow the peer to -use any IP address. (This only applies where the peer is -authenticating itself to you, of course.) - - -What's new in ppp-2.3.5. -************************ - -* Minor corrections to the Digital UNIX and NetBSD ports. - -* A workaround to avoid tickling a bug in the `se' serial port driver -on Sun PCI Ultra machines running Solaris. - -* Fixed a bug in the negotiation of the Microsoft WINS server address -option. - -* Fixed a bug in the Linux port where it would fail for kernel -versions above 2.1.99. - - -What was new in ppp-2.3.4. -************************** - -* The NeXT port has been updated, thanks to Steve Perkins. - -* ppp-2.3.4 compiles and works under Solaris 2.6, using either gcc or -cc. - -* With the Solaris, SVR4 and SunOS ports, you can control the choice -of C compiler, C compiler options, and installation directories by -editing the svr4/Makedefs or sunos4/Makedefs file. - -* Until now, we have been using the number 24 to identify Deflate -compression in the CCP negotiations, which was the number in the draft -RFC describing Deflate. The number actually assigned to Deflate is -26. The code has been changed to use 26, but to allow the use of 24 -for now for backwards compatibility. (This can be disabled with the -`nodeflatedraft' option to pppd.) - -* Fixed some bugs in the linux driver and deflate compressor which -were causing compression problems, including corrupting long -incompressible packets sometimes. - -* Fixes to the PAM and shadow password support in pppd, from Al -Longyear and others. - -* Pppd now sets some environment variables for scripts it invokes -(ip-up/down, auth-ip/down), giving information about the connection. -The variables it sets are PEERNAME, IPLOCAL, IPREMOTE, UID, DEVICE, -SPEED, and IFNAME. - -* Pppd now has an `updetach' option, which will cause it to detach -from its controlling terminal once the link has come up (i.e. once it -is available for IP traffic). - - -What was new in ppp-2.3.3. -************************** - -* Fixed compilation problems under SunOS. - -* Fixed a bug introduced into chat in 2.3.2, and compilation problems -introduced into the MS-CHAP implementation in 2.3.2. - -* The linux kernel driver has been updated for recent 2.1-series -kernel changes, and it now will ask kerneld to load compression -modules when required, if the kernel is configured to support kerneld. - -* Pppd should now compile correctly under linux on systems with glibc. - - -What was new in ppp-2.3.2. -************************** - -* In 2.3.1, I made a change which was intended to make pppd able to -detect loss of CD during or immediately after the connection script -runs. Unfortunately, this had the side-effect that the connection -script wouldn't work at all on some systems. This change has been -reversed. - -* Fix compilation problems in the Linux kernel driver. - - -What was new in ppp-2.3.1. -************************** - -* Enhancements to chat, thanks to Francis Demierre. Chat can now -accept comments in the chat script file, and has new SAY, HANGUP, -CLR_ABORT and CLR_REPORT keywords. - -* Fixed a bug which causes 2.3.0 to crash Solaris systems. - -* Bug-fixes and restructuring of the Linux kernel driver. - -* The holdoff behaviour of pppd has been changed slightly: now, if -the link comes up for IP (or other network protocol) traffic, we -consider that the link has been successfully established, and don't -enforce the holdoff period after the link goes down. - -* Pppd should now correctly wait for CD (carrier detect) from the -modem, even when the serial port initially had CLOCAL set, and it -should also detect loss of CD during or immediately after the -connection script runs. - -* Under linux, pppd will work with older 2.2.0* version kernel -drivers, although demand-dialling is not supported with them. - -* Minor bugfixes for pppd. - - -What was new in ppp-2.3. -************************ - -* Demand-dialling. Pppd now has a mode where it will establish the -network interface immediately when it starts, but not actually bring -the link up until it sees some data to be sent. Look for the demand -option description in the pppd man page. Demand-dialling is not -supported under Ultrix or NeXTStep. - -* Idle timeout. Pppd will optionally terminate the link if no data -packets are sent or received within a certain time interval. - -* Pppd now runs the /etc/ppp/auth-up script, if it exists, when the -peer successfully authenticates itself, and /etc/ppp/auth-down when -the connection is subsequently terminated. This can be useful for -accounting purposes. - -* A new packet compression scheme, Deflate, has been implemented. -This uses the same compression method as `gzip'. This method is free -of patent or copyright restrictions, and it achieves better -compression than BSD-Compress. It does consume more CPU cycles for -compression than BSD-Compress, but this shouldn't be a problem for -links running at 100kbit/s or less. - -* There is no code in this distribution which is covered by Brad -Clements' restrictive copyright notice. The STREAMS modules for SunOS -and OSF/1 have been rewritten, based on the Solaris 2 modules, which -were written from scratch without any Clements code. - -* Pppstats has been reworked to clean up the output format somewhat. -It also has a new -d option which displays data rate in kbyte/s for -those columns which would normally display bytes. - -* Pppd options beginning with - or + have been renamed, e.g. -ip -became noip, +chap became require-chap, etc. The old options are -still accepted for compatibility but may be removed in future. - -* Pppd now has some options (such as the new `noauth' option) which -can only be specified if it is being run by root, or in an -"privileged" options file: /etc/ppp/options or an options file in the -/etc/ppp/peers directory. There is a new "call" option to read -options from a file in /etc/ppp/peers, making it possible for non-root -users to make unauthenticated connections, but only to certain trusted -peers. My intention is to make the `auth' option the default in a -future release. - -* Several minor new features have been added to pppd, including the -maxconnect and welcome options. Pppd will now terminate the -connection when there are no network control protocols running. The -allowed IP address(es) field in the secrets files can now specify -subnets (with a notation like 123.45.67.89/24) and addresses which are -not acceptable (put a ! on the front). - -* Numerous bugs have been fixed (no doubt some have been introduced :-) -Thanks to those who reported bugs in ppp-2.2. - - -Patents. -******** - -The BSD-Compress algorithm used for packet compression is the same as -that used in the Unix "compress" command. It is apparently covered by -U.S. patents 4,814,746 (owned by IBM) and 4,558,302 (owned by Unisys), -and corresponding patents in various other countries (but not -Australia). If this is of concern, you can build the package without -including BSD-Compress. To do this, edit net/ppp-comp.h to change the -definition of DO_BSD_COMPRESS to 0. The bsd-comp.c files are then no -longer needed, so the references to bsd-comp.o may optionally be -removed from the Makefiles. - - -Contacts. -********* - -The comp.protocols.ppp newsgroup is a useful place to get help if you -have trouble getting your ppp connections to work. Please do not send -me questions of the form "please help me get connected to my ISP" - -I'm sorry, but I simply do not have the time to answer all the -questions like this that I get. - -If you find bugs in this package, please report them to the maintainer -for the port for the operating system you are using: - -Digital Unix (OSF/1) Farrell Woods <ftw@zk3.dec.com> -Linux Al Longyear <longyear@pobox.com> -NetBSD Matthew Green <mrg@eterna.com.au -FreeBSD Peter Wemm <peter@haywire.DIALix.COM> -NeXTStep Steve Perkins <perkins@cps.msu.edu> -Solaris 2 Paul Mackerras <Paul.Mackerras@cs.anu.edu.au> -SunOS 4.x Paul Mackerras <Paul.Mackerras@cs.anu.edu.au> -System V Release 4 Matthias Apitz <Matthias.Apitz@SOFTCON.de> -Ultrix 4.x Paul Mackerras (for want of anybody better :-) - - -Copyrights: -*********** - -All of the code can be freely used and redistributed. - - -Distribution: -************* - -The primary site for releases of this software is: - - ftp://cs.anu.edu.au/pub/software/ppp/ - -------------------------- -This is the README file for ppp-2.2, a package which implements the -Point-to-Point Protocol (PPP) to provide Internet connections over -serial lines. - - -Introduction. -************* - -The Point-to-Point Protocol (PPP) provides a standard way to transmit -datagrams over a serial link, as well as a standard way for the -machines at either end of the link (the `peers') to negotiate various -optional characteristics of the link. Using PPP, a serial link can be -used to transmit Internet Protocol (IP) datagrams, allowing TCP/IP -connections between the peers. PPP is defined in several RFC (Request -For Comments) documents, in particular RFCs 1661, 1662, 1332 and 1334. -Other RFCs describe standard ways to transmit datagrams from other -network protocols (e.g., DECnet, OSI, Appletalk), but this package -only supports IP. - -This software consists of two parts: - -- Kernel code, which establishes a network interface and passes -packets between the serial port, the kernel networking code and the -PPP daemon (pppd). This code is implemented using STREAMS modules on -SunOS 4.x, AIX 4.1 and OSF/1, and as a line discipline under Ultrix, -NextStep, NetBSD, FreeBSD, and Linux. - -- The PPP daemon (pppd), which negotiates with the peer to establish -the link and sets up the ppp network interface. Pppd includes support -for authentication, so you can control which other systems may make a -PPP connection and what IP addresses they may use. - - -What is new in ppp-2.2. -*********************** - -* More systems are now supported: - - AIX 4, thanks to Charlie Wick, - OSF/1 on DEC Alpha, thanks to Steve Tate (srt@zaphod.csci.unt.edu), - NextStep 3.2 and 3.3, thanks to Philip-Andrew Prindeville - (philipp@res.enst.fr) and Steve Perkins (perkins@cps.msu.edu), - Solaris 2, - -in addition to NetBSD 1.0, SunOS 4.x, Ultrix 4.x, FreeBSD 2.0, and -Linux. - -* Packet compression has been implemented. This version implements -CCP (Compression Control Protocol) and the BSD-Compress compression -scheme according to the current draft RFCs. This means that incoming -and outgoing packets can be compressed with the LZW scheme (same as -the `compress' command) using a code size of up to 15 bits. - -* Some bug fixes to the LCP protocol code. In particular, pppd now -correctly replies with a Configure-NAK (instead of a Configure-Reject) -if the peer asks for CHAP and pppd is willing to do PAP but not CHAP. - -* The ip-up and ip-down scripts are now run with the real user ID set -to root, and with an empty environment. Clearing the environment -fixes a security hole. - -* The kernel code on NetBSD, FreeBSD, NextStep and Ultrix has been -restructured to make it easier to implement PPP over devices other -than asynchronous tty ports (for example, synchronous serial ports). - -* pppd now looks at the list of interfaces in the system to determine -what the netmask should be. In most cases, this should eliminate the -need to use the `netmask' option. - -* There is a new `papcrypt' option to pppd, which specifies that -secrets in /etc/ppp/pap-secrets used for authenticating the peer are -encrypted, so pppd always encrypts the peer's password before -comparing it with the secret from /etc/ppp/pap-secrets. This gives -better security. - - -Patents. -******** - -The BSD-Compress algorithm used for packet compression is the same as -that used in the Unix "compress" command. It is apparently covered by -U.S. patents 4,814,746 (owned by IBM) and 4,558,302 (owned by Unisys), -and corresponding patents in various other countries (but not -Australia). If this is of concern, you can build the package without -including BSD-Compress. To do this, edit net/ppp-comp.h to change the -definition of DO_BSD_COMPRESS to 0. The bsd-comp.c files are then no -longer needed, so the references to bsd-comp.o may optionally be -removed from the Makefiles. - - -Contacts. -********* - -Bugs in the the SunOS, NetBSD and Ultrix ports and bugs in pppd, chat -or pppstats should be reported to: - - paulus@cs.anu.edu.au - Paul Mackerras - Dept. of Computer Science - Australian National University - Canberra ACT 0200 - AUSTRALIA - -Bugs in other ports should be reported to the maintainer for that port -(see the appropriate README.* file) or to the above. Unfortunately, -Charlie Wick is not in a position to provide support for the AIX 4 -port, so if you find bugs in it, send them to me. - -Thanks to: - - Brad Parker (brad@fcr.com) - Greg Christy (gmc@quotron.com) - Drew D. Perkins (ddp@andrew.cmu.edu) - Rick Adams (rick@seismo.ARPA) - Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). - - -Copyrights: - -Most of the code can be freely used and redistributed. The STREAMS -code for SunOS 4.x, OSF/1 and AIX 4 is under a more restrictive -copyright: - - This code is Copyright (C) 1989, 1990 By Brad K. Clements, - All Rights Reserved. - - You may use this code for your personal use, to provide a non-profit - service to others, or to use as a test platform for a commercial - implementation. - - You may NOT use this code in a commercial product, nor to provide a - commercial service, nor may you sell this code without express - written permission of the author. - - Otherwise, Enjoy! - -This copyright applies to (parts of) the following files: - - sunos/ppp_async.c - sunos/ppp_if.c - aix4/ppp_async.c - aix4/ppp_if.c - net/ppp_str.h - pppd/sys-str.c - pppd/sys-osf.c - pppd/sys-aix4.c -------------------------- - pppd-2.1.1 release notes - Paul Mackerras 27 May 1994 - -This file details the new and changed features in pppd since version 1.3. -Briefly: - - the protocol code has been updated to conform with - RFCs 1548, 1549, 1332 and 1334 - - security has been improved - - functionality has been improved in various ways. - - -NEW FEATURES - -* The option negotiation automaton has been updated to RFC1548. LCP -now rejects the Quality Protocol option, since LQR is not implemented -yet. IPCP now uses the IP-Address option, and falls back to the old -IP-Addresses option if the IP-Address option is rejected. IPCP also -uses the new form of the VJ-Compression option. - -RFC1548 defines the "passive" option to mean that the automaton -outputs configure-request packets initially, but does not close down -if no answer is received. A valid configure-request received will -restart the negotiation. The "silent" option has been added with the -old meaning of "passive", i.e. the automaton will not output -configure-requests until it receives a valid one from the peer. - -* More systems are supported: in addition to SunOS 4.x and BSD/Net-2 -derived systems, Ultrix and Linux are supported, thanks to Robert -Olsson, Per Sundstrom, Michael Callahan and Al Longyear. - -* Options can be taken from files as well as the command line. pppd -reads options from the files /etc/ppp/options and ~/.ppprc before -looking at the command line, and /etc/ppp/options.<ttyname> after -interpreting the options on the command line. An options file is -parsed into a series of words, delimited by whitespace. Whitespace -can be included in a word by enclosing the word in quotes ("). -Backslash (\) quotes the following character. A hash (#) starts a -comment, which continues until the end of the line. In addition, the -`file' option causes pppd to read options from a file. pppd will -report and error and exit if ~/.ppprc or the file given as the -argument to the `file' option cannot be read by the user who invoked -pppd. - -* On those systems, such as NetBSD, where the serial line speed is -stored in the termios structure in bits per second (i.e. B9600 == -9600), it is possible to set any speed. - -* If desired, pppd will output LCP echo-request frames periodically -while the link is up, and take the link down if no replies are -received to a user-configurable number of echo-requests. This can be -used to detect that the serial connection has been broken on those -systems which don't have hardware modem control lines. - -AUTHENTICATION - -Previous versions of pppd have provided no control over which IP -addresses the peer can use. Thus it is possible for the peer to -impersonate another host on the local network, leading to various -security holes. In addition, the authentication mechanisms were quite -weak: if the peer refused to agree to authenticate, pppd would print a -warning message but still allow the link to come up. The CHAP -implementation also appeared to be quite broken (has anybody actually -used it?). - -This new version of pppd addresses these problems. My aim has been to -provide system administrators with sufficient access control that PPP -access to a server machine can be provided to legitimate users without -fear of compromising the security of the server or the network it's -on. In part this is provided by the /etc/ppp/options file, where the -administrator can place options to require authentication which cannot -be disabled by users. Thus the new pppd can made setuid-root and run -by users. - -The behaviour where pppd refuses to run unless the /etc/ppp/options -file is present and readable by pppd is now the default behaviour. If -you really want pppd to run without the presence of the -/etc/ppp/options file, you will have to include -DREQ_SYSOPTIONS=0 on -the compilation command line. - -The options related to authentication are: - - auth Require authentication from the peer. If neither - +chap or +pap is also given, either CHAP or PAP - authentication will be accepted. - +chap Require CHAP authentication from the peer. - +pap Require PAP authentication from the peer. - -chap Don't agree to authenticate ourselves with the peer - using CHAP. - -pap Don't agree to authenticate ourselves using PAP. - +ua <f> Get username and password for authenticating ourselves - with the peer using PAP from file <f>. - name <n> Use <n> as the local name for authentication. - usehostname Use this machine's hostname as the local name for - authentication. - remotename <n> Use <n> as the name of the peer for authentication. - login If the peer authenticates using PAP, check the - supplied username and password against the system - password database, and make a wtmp entry. - user <n> Use <n> as the username for authenticating ourselves - using PAP. - -The defaults are to agree to authenticate if requested, and to not -require authentication from the peer. However, pppd will not agree to -authenticate itself with a particular protocol if it has no secrets -which could be used to do so. - -Authentication is based on secrets, which are selected from secrets -files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP). -Both secrets files have the same format, and both can store secrets -for several combinations of server (authenticating peer) and client -(peer being authenticated). Note that each end can be both a server -and client, and that different protocols can be used in the two -directions if desired. - -A secrets file is parsed into words as for an options file. A secret -is specified by a line containing at least 3 words, in the order -client, server, secret. Any following words on the same line are -taken to be a list of acceptable IP addresses for that client. If -there are only 3 words on the line, it is assumed that any IP address -is OK; to disallow all IP addresses, use "-". If the secret starts -with an `@', what follows is assumed to be the name of a file from -which to read the secret. A "*" as the client or server name matches -any name. When selecting a secret, pppd takes the best match, i.e. -the match with the fewest wildcards. - -Thus a secrets file contains both secrets for use in authenticating -other hosts, plus secrets which we use for authenticating ourselves to -others. Which secret to use is chosen based on the names of the host -(the `local name') and its peer (the `remote name'). The local name -is set as follows: - - if the `usehostname' option is given, - then the local name is the hostname of this machine - (with the domain appended, if given) - - else if the `name' option is given, - then use the argument of the first `name' option seen - - else if the local IP address is specified with a - host name (e.g. `sirius:') - then use that host name - - else use the hostname of this machine - (with the domain appended, if given) - -When authenticating ourselves using PAP, there is also a `username' -which is the local name by default, but can be set with the `user' -option or the `+ua' option. - -The remote name is set as follows: - - if the `remotename' option is given, - then use the argument of the last `remotename' option seen - - else if the remote IP address is specified with a - host name (e.g. `avago:') - then use that host name - - else the remote name is the null string "". - -Secrets are selected from the PAP secrets file as follows: - -- For authenticating the peer, look for a secret with client == -username specified in the PAP authenticate-request, and server == -local name. - -- For authenticating ourselves to the peer, look for a secret with -client == our username, server == remote name. - -When authenticating the peer with PAP, a secret of "" matches any -password supplied by the peer. If the password doesn't match the -secret, the password is encrypted using crypt() and checked against -the secret again; thus secrets for authenticating the peer can be -stored in encrypted form. If the `login' option was specified, the -username and password are also checked against the system password -database. Thus, the system administrator can set up the pap-secrets -file to allow PPP access only to certain users, and to restrict the -set of IP addresses that each user can use. - -Secrets are selected from the CHAP secrets file as follows: - -- For authenticating the peer, look for a secret with client == name -specified in the CHAP-Response message, and server == local name. - -- For authenticating ourselves to the peer, look for a secret with -client == local name, and server == name specified in the -CHAP-Challenge message. - -Authentication must be satisfactorily completed before IPCP (or any -other Network Control Protocol) can be started. If authentication -fails, pppd will terminated the link (by closing LCP). If IPCP -negotiates an unacceptable IP address for the remote host, IPCP will -be closed. IP packets cannot be sent or received until IPCP is -successfully opened. - -(some examples needed here perhaps) - - -ROUTING - -Setting the addresses on a ppp interface is sufficient to create a -host route to the remote end of the link. Sometimes it is desirable -to add a default route through the remote host, as in the case of a -machine whose only connection to the Internet is through the ppp -interface. The `defaultroute' option causes pppd to create such a -default route when IPCP comes up, and delete it when the link is -terminated. - -In some cases it is desirable to use proxy ARP, for example on a -server machine connected to a LAN, in order to allow other hosts to -communicate with the remote host. The `proxyarp' option causes pppd -to look for a network interface (an interface supporting broadcast and -ARP, which is up and not a point-to-point or loopback interface) on -the same subnet as the remote host. If found, pppd creates a -permanent, published ARP entry with the IP address of the remote host -and the hardware address of the network interface found. - - -OTHER NEW AND CHANGED OPTIONS - - modem Use modem control lines (not fully implemented - yet) - local Don't use modem control lines - persist Keep reopening connection (not fully - implemented yet) - - lcp-restart <n> Set timeout for LCP retransmissions to <n> - seconds (default 3 seconds) - lcp-max-terminate <n> Set maximum number of LCP terminate-request - transmissions (default 2) - lcp-max-configure <n> Set maximum number of LCP configure-request - transmissions (default 10) - lcp-max-failure <n> Set maximum number of LCP configure-Naks sent - before converting to configure-rejects - (default 10) - - ipcp-restart <n> Set timeout for IPCP retransmissions to <n> - seconds (default 3 seconds) - ipcp-max-terminate <n> Set maximum number of IPCP - terminate-request transmissions (default 2) - ipcp-max-configure <n> Set maximum number of IPCP - configure-request transmissions (default 10) - ipcp-max-failure <n> Set maximum number of IPCP configure-Naks - sent before converting to configure-rejects - (default 10) - - upap-restart <n> Set timeout for PAP retransmissions to - <n> seconds (default 3 seconds) - upap-max-authreq <n> Set maximum number of Authenticate-request - retransmissions (default 10) - - chap-restart <n> Set timeout for CHAP retransmissions to - <n> seconds (default 3 seconds) - chap-max-challenge <n> Set maximum number of CHAP Challenge - retransmissions (default 10) - chap-interval <n> Set the interval between CHAP rechallenges - (default 0, meaning infinity) - -The -ua option no longer exists. - - -SOFTWARE RESTRUCTURING - -Many of the source files for pppd have changed significantly from -ppp-1.3, upon which it is based. In particular: - -- the macros for system-dependent operations in pppd.h have mostly -been removed. Instead these operations are performed by procedures in -sys-bsd.c (for BSD-4.4ish systems like NetBSD, 386BSD, etc.) or -sys-str.c (for SunOS-based systems using STREAMS). (I got sick of -having to recompile everything every time I wanted to change one of -those horrible macros.) - -- most of the system-dependent code in main.c has also been removed to -sys-bsd.c and sys-str.c. - -- the option processing code in main.c has been removed to options.c. - -- the authentication code in main.c has been removed to auth.c, which -also contains substantial amounts of new code. - -- fsm.c has changed significantly, and lcp.c, ipcp.c, and upap.c have -changed somewhat. chap.c has also changed significantly. - - -STILL TO DO - -* sort out appropriate modem control and implement the persist option -properly; add an `answer' option for auto-answering a modem. - -* add an inactivity timeout and demand dialing. - -* implement link quality monitoring. - -* implement other network control protocols. diff --git a/usr.sbin/pppd/auth.c b/usr.sbin/pppd/auth.c deleted file mode 100644 index a0062da..0000000 --- a/usr.sbin/pppd/auth.c +++ /dev/null @@ -1,1637 +0,0 @@ -/* - * auth.c - PPP authentication and phase control. - * - * Copyright (c) 1993 The Australian National 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 the Australian National 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. - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#include <stdio.h> -#include <stddef.h> -#include <stdlib.h> -#include <unistd.h> -#include <syslog.h> -#include <paths.h> -#include <pwd.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <utmp.h> -#include <fcntl.h> -#if defined(_PATH_LASTLOG) && defined(_linux_) -#include <lastlog.h> -#endif - -#include <netdb.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/time.h> -#include <utmp.h> - -#ifdef USE_PAM -#include <security/pam_appl.h> -#endif - -#ifdef HAS_SHADOW -#include <shadow.h> -#ifndef PW_PPP -#define PW_PPP PW_LOGIN -#endif -#endif - -#include "pppd.h" -#include "fsm.h" -#include "lcp.h" -#include "ipcp.h" -#include "upap.h" -#include "chap.h" -#ifdef CBCP_SUPPORT -#include "cbcp.h" -#endif -#include "pathnames.h" - -/* Used for storing a sequence of words. Usually malloced. */ -struct wordlist { - struct wordlist *next; - char word[1]; -}; - -/* Bits in scan_authfile return value */ -#define NONWILD_SERVER 1 -#define NONWILD_CLIENT 2 - -#define ISWILD(word) (word[0] == '*' && word[1] == 0) - -#define FALSE 0 -#define TRUE 1 - -/* The name by which the peer authenticated itself to us. */ -char peer_authname[MAXNAMELEN]; - -/* Records which authentication operations haven't completed yet. */ -static int auth_pending[NUM_PPP]; - -/* Set if we have successfully called plogin() */ -static int logged_in; - -/* Set if not wild or blank */ -static int non_wildclient; - -/* Set if we have run the /etc/ppp/auth-up script. */ -static int did_authup; - -/* List of addresses which the peer may use. */ -static struct wordlist *addresses[NUM_PPP]; - -/* Number of network protocols which we have opened. */ -static int num_np_open; - -/* Number of network protocols which have come up. */ -static int num_np_up; - -/* Set if we got the contents of passwd[] from the pap-secrets file. */ -static int passwd_from_file; - -/* Bits in auth_pending[] */ -#define PAP_WITHPEER 1 -#define PAP_PEER 2 -#define CHAP_WITHPEER 4 -#define CHAP_PEER 8 - -extern char *crypt(const char *, const char *); - -/* Prototypes for procedures local to this file. */ - -static void network_phase(int); -static void check_idle(void *); -static void connect_time_expired(void *); -static int plogin(char *, char *, char **, int *); -static void plogout(void); -static int null_login(int); -static int get_pap_passwd(char *); -static int have_pap_secret(void); -static int have_chap_secret(char *, char *, u_int32_t); -static int ip_addr_check(u_int32_t, struct wordlist *); -static int scan_authfile(FILE *, char *, char *, u_int32_t, char *, - struct wordlist **, char *); -static void free_wordlist(struct wordlist *); -static void auth_set_ip_addr(int); -static void auth_script(char *); -static void set_allowed_addrs(int, struct wordlist *); - -/* - * An Open on LCP has requested a change from Dead to Establish phase. - * Do what's necessary to bring the physical layer up. - */ -void -link_required(unit) - int unit; -{ -} - -/* - * LCP has terminated the link; go to the Dead phase and take the - * physical layer down. - */ -void -link_terminated(unit) - int unit; -{ - extern time_t etime, stime; - extern int minutes; - - if (phase == PHASE_DEAD) - return; - if (logged_in) - plogout(); - phase = PHASE_DEAD; - etime = time((time_t *) NULL); - minutes = (etime-stime)/60; - syslog(LOG_NOTICE, "Connection terminated, connected for %d minutes\n", - minutes > 1 ? minutes : 1); -} - -/* - * LCP has gone down; it will either die or try to re-establish. - */ -void -link_down(unit) - int unit; -{ - int i; - struct protent *protp; - - if (did_authup) { - auth_script(_PATH_AUTHDOWN); - did_authup = 0; - } - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (!protp->enabled_flag) - continue; - if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) - (*protp->lowerdown)(unit); - if (protp->protocol < 0xC000 && protp->close != NULL) - (*protp->close)(unit, "LCP down"); - } - num_np_open = 0; - num_np_up = 0; - if (phase != PHASE_DEAD) - phase = PHASE_TERMINATE; -} - -/* - * The link is established. - * Proceed to the Dead, Authenticate or Network phase as appropriate. - */ -void -link_established(unit) - int unit; -{ - int auth; - lcp_options *wo = &lcp_wantoptions[unit]; - lcp_options *go = &lcp_gotoptions[unit]; - lcp_options *ho = &lcp_hisoptions[unit]; - int i; - struct protent *protp; - - /* - * Tell higher-level protocols that LCP is up. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol != PPP_LCP && protp->enabled_flag - && protp->lowerup != NULL) - (*protp->lowerup)(unit); - - if (auth_required && !(go->neg_chap || go->neg_upap)) { - /* - * We wanted the peer to authenticate itself, and it refused: - * treat it as though it authenticated with PAP using a username - * of "" and a password of "". If that's not OK, boot it out. - */ - if (!wo->neg_upap || !null_login(unit)) { - syslog(LOG_WARNING, "peer refused to authenticate"); - lcp_close(unit, "peer refused to authenticate"); - return; - } - } - - phase = PHASE_AUTHENTICATE; - auth = 0; - if (go->neg_chap) { - ChapAuthPeer(unit, our_name, go->chap_mdtype); - auth |= CHAP_PEER; - } else if (go->neg_upap) { - upap_authpeer(unit); - auth |= PAP_PEER; - } - if (ho->neg_chap) { - ChapAuthWithPeer(unit, user, ho->chap_mdtype); - auth |= CHAP_WITHPEER; - } else if (ho->neg_upap) { - if (passwd[0] == 0) { - passwd_from_file = 1; - if (!get_pap_passwd(passwd)) - syslog(LOG_ERR, "No secret found for PAP login"); - } - upap_authwithpeer(unit, user, passwd); - auth |= PAP_WITHPEER; - } - auth_pending[unit] = auth; - - if (!auth) - network_phase(unit); -} - -/* - * Proceed to the network phase. - */ -static void -network_phase(unit) - int unit; -{ - int i; - struct protent *protp; - lcp_options *go = &lcp_gotoptions[unit]; - - /* - * If the peer had to authenticate, run the auth-up script now. - */ - if ((go->neg_chap || go->neg_upap) && !did_authup) { - auth_script(_PATH_AUTHUP); - did_authup = 1; - } - -#ifdef CBCP_SUPPORT - /* - * If we negotiated callback, do it now. - */ - if (go->neg_cbcp) { - phase = PHASE_CALLBACK; - (*cbcp_protent.open)(unit); - return; - } -#endif - - phase = PHASE_NETWORK; -#if 0 - if (!demand) - set_filters(&pass_filter, &active_filter); -#endif - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol < 0xC000 && protp->enabled_flag - && protp->open != NULL) { - (*protp->open)(unit); - if (protp->protocol != PPP_CCP) - ++num_np_open; - } - - if (num_np_open == 0) - /* nothing to do */ - lcp_close(0, "No network protocols running"); -} - -/* - * The peer has failed to authenticate himself using `protocol'. - */ -void -auth_peer_fail(unit, protocol) - int unit, protocol; -{ - /* - * Authentication failure: take the link down - */ - lcp_close(unit, "Authentication failed"); -} - -/* - * The peer has been successfully authenticated using `protocol'. - */ -void -auth_peer_success(unit, protocol, name, namelen) - int unit, protocol; - char *name; - int namelen; -{ - int bit; - - switch (protocol) { - case PPP_CHAP: - bit = CHAP_PEER; - break; - case PPP_PAP: - bit = PAP_PEER; - break; - default: - syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x", - protocol); - return; - } - - /* - * Save the authenticated name of the peer for later. - */ - if (namelen > sizeof(peer_authname) - 1) - namelen = sizeof(peer_authname) - 1; - BCOPY(name, peer_authname, namelen); - peer_authname[namelen] = 0; - - /* - * If we have overridden addresses based on auth info - * then set that information now before continuing. - */ - auth_set_ip_addr(unit); - - script_setenv("PEERNAME", peer_authname); - - /* - * If there is no more authentication still to be done, - * proceed to the network (or callback) phase. - */ - if ((auth_pending[unit] &= ~bit) == 0) - network_phase(unit); -} - -/* - * We have failed to authenticate ourselves to the peer using `protocol'. - */ -void -auth_withpeer_fail(unit, protocol) - int unit, protocol; -{ - if (passwd_from_file) - BZERO(passwd, MAXSECRETLEN); - /* - * We've failed to authenticate ourselves to our peer. - * He'll probably take the link down, and there's not much - * we can do except wait for that. - */ -} - -/* - * We have successfully authenticated ourselves with the peer using `protocol'. - */ -void -auth_withpeer_success(unit, protocol) - int unit, protocol; -{ - int bit; - - switch (protocol) { - case PPP_CHAP: - bit = CHAP_WITHPEER; - break; - case PPP_PAP: - if (passwd_from_file) - BZERO(passwd, MAXSECRETLEN); - bit = PAP_WITHPEER; - break; - default: - syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x", - protocol); - bit = 0; - } - - /* - * If we have overridden addresses based on auth info - * then set that information now before continuing. - */ - auth_set_ip_addr(unit); - - /* - * If there is no more authentication still being done, - * proceed to the network (or callback) phase. - */ - if ((auth_pending[unit] &= ~bit) == 0) - network_phase(unit); -} - - -/* - * np_up - a network protocol has come up. - */ -void -np_up(unit, proto) - int unit, proto; -{ - if (num_np_up == 0) { - /* - * At this point we consider that the link has come up successfully. - */ - need_holdoff = 0; - - if (idle_time_limit > 0) - TIMEOUT(check_idle, NULL, idle_time_limit); - - /* - * Set a timeout to close the connection once the maximum - * connect time has expired. - */ - if (maxconnect > 0) - TIMEOUT(connect_time_expired, 0, maxconnect); - - /* - * Detach now, if the updetach option was given. - */ - if (nodetach == -1) - detach(); - } - ++num_np_up; -} - -/* - * np_down - a network protocol has gone down. - */ -void -np_down(unit, proto) - int unit, proto; -{ - if (--num_np_up == 0 && idle_time_limit > 0) { - UNTIMEOUT(check_idle, NULL); - } -} - -/* - * np_finished - a network protocol has finished using the link. - */ -void -np_finished(unit, proto) - int unit, proto; -{ - if (--num_np_open <= 0) { - /* no further use for the link: shut up shop. */ - lcp_close(0, "No network protocols running"); - } -} - -/* - * check_idle - check whether the link has been idle for long - * enough that we can shut it down. - */ -static void -check_idle(arg) - void *arg; -{ - struct ppp_idle idle; - time_t itime; - - if (!get_idle_time(0, &idle)) - return; - itime = MIN(idle.xmit_idle, idle.recv_idle); - if (itime >= idle_time_limit) { - /* link is idle: shut it down. */ - syslog(LOG_INFO, "Terminating connection due to lack of activity."); - lcp_close(0, "Link inactive"); - } else { - TIMEOUT(check_idle, NULL, idle_time_limit - itime); - } -} - -/* - * connect_time_expired - log a message and close the connection. - */ -static void -connect_time_expired(arg) - void *arg; -{ - syslog(LOG_INFO, "Connect time expired"); - lcp_close(0, "Connect time expired"); /* Close connection */ -} - -/* - * auth_check_options - called to check authentication options. - */ -void -auth_check_options() -{ - lcp_options *wo = &lcp_wantoptions[0]; - int can_auth; - ipcp_options *ipwo = &ipcp_wantoptions[0]; - u_int32_t remote; - - /* Default our_name to hostname, and user to our_name */ - if (our_name[0] == 0 || usehostname) - strcpy(our_name, hostname); - if (user[0] == 0) - strcpy(user, our_name); - - /* If authentication is required, ask peer for CHAP or PAP. */ - if (auth_required && !wo->neg_chap && !wo->neg_upap) { - wo->neg_chap = 1; - wo->neg_upap = 1; - } - - /* - * Check whether we have appropriate secrets to use - * to authenticate the peer. - */ - can_auth = wo->neg_upap && (uselogin || have_pap_secret()); - if (!can_auth && wo->neg_chap) { - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - can_auth = have_chap_secret(remote_name, our_name, remote); - } - - if (auth_required && !can_auth) { - option_error("peer authentication required but no suitable secret(s) found\n"); - if (remote_name[0] == 0) - option_error("for authenticating any peer to us (%s)\n", our_name); - else - option_error("for authenticating peer %s to us (%s)\n", - remote_name, our_name); - exit(1); - } - - /* - * Check whether the user tried to override certain values - * set by root. - */ - if (!auth_required && auth_req_info.priv > 0) { - if (!default_device && devnam_info.priv == 0) { - option_error("can't override device name when noauth option used"); - exit(1); - } - if ((connector != NULL && connector_info.priv == 0) - || (disconnector != NULL && disconnector_info.priv == 0) - || (welcomer != NULL && welcomer_info.priv == 0)) { - option_error("can't override connect, disconnect or welcome"); - option_error("option values when noauth option used"); - exit(1); - } - } -} - -/* - * auth_reset - called when LCP is starting negotiations to recheck - * authentication options, i.e. whether we have appropriate secrets - * to use for authenticating ourselves and/or the peer. - */ -void -auth_reset(unit) - int unit; -{ - lcp_options *go = &lcp_gotoptions[unit]; - lcp_options *ao = &lcp_allowoptions[0]; - ipcp_options *ipwo = &ipcp_wantoptions[0]; - u_int32_t remote; - - ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); - ao->neg_chap = !refuse_chap - && have_chap_secret(user, remote_name, (u_int32_t)0); - - if (go->neg_upap && !uselogin && !have_pap_secret()) - go->neg_upap = 0; - if (go->neg_chap) { - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - if (!have_chap_secret(remote_name, our_name, remote)) - go->neg_chap = 0; - } -} - - -/* - * check_passwd - Check the user name and passwd against the PAP secrets - * file. If requested, also check against the system password database, - * and login the user if OK. - * - * returns: - * UPAP_AUTHNAK: Authentication failed. - * UPAP_AUTHACK: Authentication succeeded. - * In either case, msg points to an appropriate message. - */ -int -check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) - int unit; - char *auser; - int userlen; - char *apasswd; - int passwdlen; - char **msg; - int *msglen; -{ - int ret; - char *filename; - FILE *f; - struct wordlist *addrs; - u_int32_t remote; - ipcp_options *ipwo = &ipcp_wantoptions[unit]; - char passwd[256], user[256]; - char secret[MAXWORDLEN]; - static int attempts = 0; - int len; - - /* - * Make copies of apasswd and auser, then null-terminate them. - */ - len = MIN(passwdlen, sizeof(passwd) - 1); - BCOPY(apasswd, passwd, len); - passwd[len] = '\0'; - len = MIN(userlen, sizeof(user) - 1); - BCOPY(auser, user, len); - user[len] = '\0'; - *msg = (char *) 0; - - /* - * Open the file of pap secrets and scan for a suitable secret - * for authenticating this user. - */ - filename = _PATH_UPAPFILE; - addrs = NULL; - ret = UPAP_AUTHACK; - f = fopen(filename, "r"); - if (f == NULL) { - syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename); - ret = UPAP_AUTHNAK; - - } else { - check_access(f, filename); - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - if (scan_authfile(f, user, our_name, remote, - secret, &addrs, filename) < 0) { - warn("no PAP secret found for %s", user); - } else { - if (secret[0] != 0) { - /* password given in pap-secrets - must match */ - if ((cryptpap || strcmp(passwd, secret) != 0) - && strcmp(crypt(passwd, secret), secret) != 0) { - ret = UPAP_AUTHNAK; - warn("PAP authentication failure for %s", user); - } - } - } - fclose(f); - } - - if (uselogin && ret == UPAP_AUTHACK) { - ret = plogin(user, passwd, msg, msglen); - if (ret == UPAP_AUTHNAK) { - syslog(LOG_WARNING, "PAP login failure for %s", user); - } - } - - if (ret == UPAP_AUTHNAK) { - if (*msg == (char *) 0) - *msg = "Login incorrect"; - *msglen = strlen(*msg); - /* - * Frustrate passwd stealer programs. - * Allow 10 tries, but start backing off after 3 (stolen from login). - * On 10'th, drop the connection. - */ - if (attempts++ >= 10) { - syslog(LOG_WARNING, "%d LOGIN FAILURES ON %s, %s", - attempts, devnam, user); - quit(); - } - if (attempts > 3) - sleep((u_int) (attempts - 3) * 5); - if (addrs != NULL) - free_wordlist(addrs); - - } else { - attempts = 0; /* Reset count */ - if (*msg == (char *) 0) - *msg = "Login ok"; - *msglen = strlen(*msg); - set_allowed_addrs(unit, addrs); - } - - BZERO(passwd, sizeof(passwd)); - BZERO(secret, sizeof(secret)); - - return ret; -} - -/* - * Check if an "entry" is in the file "fname" - used by ppplogin. - * Taken from libexec/ftpd/ftpd.c - * Returns: 0 if not found, 1 if found, 2 if file can't be opened for reading. - */ -static int -checkfile(fname, name) - char *fname; - char *name; -{ - FILE *fd; - int found = 0; - char *p, line[BUFSIZ]; - - if ((fd = fopen(fname, "r")) != NULL) { - while (fgets(line, sizeof(line), fd) != NULL) - if ((p = strchr(line, '\n')) != NULL) { - *p = '\0'; - if (line[0] == '#') - continue; - if (strcmp(line, name) == 0) { - found = 1; - break; - } - } - (void) fclose(fd); - } else { - return(2); - } - return (found); -} - -/* - * This function is needed for PAM. - */ - -#ifdef USE_PAM -static char *PAM_username = ""; -static char *PAM_password = ""; - -#ifdef PAM_ESTABLISH_CRED /* new PAM defines :(^ */ -#define MY_PAM_STRERROR(err_code) (char *) pam_strerror(pamh,err_code) -#else -#define MY_PAM_STRERROR(err_code) (char *) pam_strerror(err_code) -#endif - -static int pam_conv (int num_msg, - const struct pam_message **msg, - struct pam_response **resp, - void *appdata_ptr) -{ - int count = 0, replies = 0; - struct pam_response *reply = NULL; - int size = 0; - - for (count = 0; count < num_msg; count++) - { - size += sizeof (struct pam_response); - reply = realloc (reply, size); /* ANSI: is malloc() if reply==NULL */ - if (!reply) - return PAM_CONV_ERR; - - switch (msg[count]->msg_style) - { - case PAM_PROMPT_ECHO_ON: - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = strdup(PAM_username); /* never NULL */ - break; - - case PAM_PROMPT_ECHO_OFF: - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = strdup(PAM_password); /* never NULL */ - break; - - case PAM_TEXT_INFO: - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = NULL; - break; - - case PAM_ERROR_MSG: - default: - free (reply); - return PAM_CONV_ERR; - } - } - - if (resp) - *resp = reply; - else - free (reply); - - return PAM_SUCCESS; -} -#endif - -/* - * plogin - Check the user name and password against the system - * password database, and login the user if OK. - * - * returns: - * UPAP_AUTHNAK: Login failed. - * UPAP_AUTHACK: Login succeeded. - * In either case, msg points to an appropriate message. - * - * UPAP_AUTHACK should only be returned *after* wtmp and utmp are updated. - */ - -static int -plogin(user, passwd, msg, msglen) - char *user; - char *passwd; - char **msg; - int *msglen; -{ - -#ifdef USE_PAM - - struct pam_conv pam_conversation; - pam_handle_t *pamh; - int pam_error; -/* - * Fill the pam_conversion structure - */ - memset (&pam_conversation, '\0', sizeof (struct pam_conv)); - pam_conversation.conv = &pam_conv; - - pam_error = pam_start ("ppp", user, &pam_conversation, &pamh); - - if (pam_error != PAM_SUCCESS) { - *msg = MY_PAM_STRERROR (pam_error); - return UPAP_AUTHNAK; - } -/* - * Define the fields for the credintial validation - */ - (void) pam_set_item (pamh, PAM_TTY, devnam); - PAM_username = user; - PAM_password = passwd; -/* - * Validate the user - */ - pam_error = pam_authenticate (pamh, PAM_SILENT); - if (pam_error == PAM_SUCCESS) { - pam_error = pam_acct_mgmt (pamh, PAM_SILENT); - - /* start a session for this user. Session closed when link ends. */ - if (pam_error == PAM_SUCCESS) - (void) pam_open_session (pamh, PAM_SILENT); - } - - *msg = MY_PAM_STRERROR (pam_error); - - PAM_username = - PAM_password = ""; -/* - * Clean up the mess - */ - (void) pam_end (pamh, pam_error); - - if (pam_error != PAM_SUCCESS) - return UPAP_AUTHNAK; -/* - * Use the non-PAM methods directly - */ -#else /* #ifdef USE_PAM */ - - struct passwd *pw; - struct utmp utmp; - struct timeval tp; - char *tty; - -#ifdef HAS_SHADOW - struct spwd *spwd; - struct spwd *getspnam(); -#endif - - pw = getpwnam(user); - endpwent(); - if (pw == NULL) { - return (UPAP_AUTHNAK); - } -/* - * Check that the user is not listed in /etc/ppp/ppp.deny - * and that the user's shell is listed in /etc/ppp/ppp.shells - * if /etc/ppp/ppp.shells exists. - */ - - if (checkfile(_PATH_PPPDENY, user) == 1) { - syslog(LOG_WARNING, "upap user %s: login denied in %s", - user, _PATH_PPPDENY); - return (UPAP_AUTHNAK); - } - - if (checkfile(_PATH_PPPSHELLS, pw->pw_shell) == 0) { - syslog(LOG_WARNING, "upap user %s: shell %s not in %s", - user, pw->pw_shell, _PATH_PPPSHELLS); - return (UPAP_AUTHNAK); - } - -#ifdef HAS_SHADOW - spwd = getspnam(user); - endspent(); - if (spwd) { - /* check the age of the password entry */ - long now = time(NULL) / 86400L; - - if ((spwd->sp_expire > 0 && now >= spwd->sp_expire) - || ((spwd->sp_max >= 0 && spwd->sp_max < 10000) - && spwd->sp_lstchg >= 0 - && now >= spwd->sp_lstchg + spwd->sp_max)) { - syslog(LOG_WARNING, "Password for %s has expired", user); - return (UPAP_AUTHNAK); - } - pw->pw_passwd = spwd->sp_pwdp; - } -#endif - - /* - * If no passwd, don't let them login. - */ - if (pw->pw_passwd == NULL || *pw->pw_passwd == '\0' - || strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0) - return (UPAP_AUTHNAK); - - if (pw->pw_expire) { - (void)gettimeofday(&tp, (struct timezone *)NULL); - if (tp.tv_sec >= pw->pw_expire) { - syslog(LOG_INFO, "pap user %s account expired", user); - return (UPAP_AUTHNAK); - } - } - - /* These functions are not enabled for PAM. The reason for this is that */ - /* there is not necessarily a "passwd" entry for this user. That is */ - /* real purpose of 'PAM' -- to virtualize the account data from the */ - /* application. If you want to do the same thing, write the entry in */ - /* the 'session' hook. */ - - /* Log in wtmp and utmp using login() */ - - tty = devnam; - if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0) - tty += 5; - - if (logout(tty)) /* Already entered (by login?) */ - logwtmp(tty, "", ""); - -#if defined(_PATH_LASTLOG) - { - struct lastlog ll; - int fd; - - if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { - (void)lseek(fd, (off_t)(pw->pw_uid * sizeof(ll)), SEEK_SET); - memset((void *)&ll, 0, sizeof(ll)); - ll.ll_time = _time_to_time32(time(0)); - (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); - (void)write(fd, (char *)&ll, sizeof(ll)); - (void)close(fd); - } - } -#endif - - memset((void *)&utmp, 0, sizeof(utmp)); - utmp.ut_time = time(NULL); - (void)strncpy(utmp.ut_name, user, sizeof(utmp.ut_name)); - (void)strncpy(utmp.ut_host, ":PPP", sizeof(utmp.ut_host)); - (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); - login(&utmp); /* This logs us in wtmp too */ - -#endif /* #ifdef USE_PAM */ - - syslog(LOG_INFO, "user %s logged in", user); - logged_in = TRUE; - - return (UPAP_AUTHACK); -} - -/* - * plogout - Logout the user. - */ -static void -plogout() -{ -#ifdef USE_PAM - struct pam_conv pam_conversation; - pam_handle_t *pamh; - int pam_error; -/* - * Fill the pam_conversion structure. The PAM specification states that the - * session must be able to be closed by a totally different handle from which - * it was created. Hold the PAM group to their own specification! - */ - memset (&pam_conversation, '\0', sizeof (struct pam_conv)); - pam_conversation.conv = &pam_conv; - - pam_error = pam_start ("ppp", user, &pam_conversation, &pamh); - if (pam_error == PAM_SUCCESS) { - (void) pam_set_item (pamh, PAM_TTY, devnam); - (void) pam_close_session (pamh, PAM_SILENT); - (void) pam_end (pamh, PAM_SUCCESS); - } - -#else - char *tty; - - tty = devnam; - if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0) - tty += 5; - logwtmp(tty, "", ""); /* Wipe out wtmp logout entry */ - logout(tty); /* Wipe out utmp */ -#endif - - logged_in = FALSE; -} - - -/* - * null_login - Check if a username of "" and a password of "" are - * acceptable, and iff so, set the list of acceptable IP addresses - * and return 1. - */ -static int -null_login(unit) - int unit; -{ - char *filename; - FILE *f; - int i, ret; - struct wordlist *addrs; - char secret[MAXWORDLEN]; - - /* - * Open the file of pap secrets and scan for a suitable secret. - * We don't accept a wildcard client. - */ - filename = _PATH_UPAPFILE; - addrs = NULL; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - check_access(f, filename); - - i = scan_authfile(f, "", our_name, (u_int32_t)0, secret, &addrs, filename); - ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0; - BZERO(secret, sizeof(secret)); - - if (ret) - set_allowed_addrs(unit, addrs); - else - free_wordlist(addrs); - - fclose(f); - return ret; -} - - -/* - * get_pap_passwd - get a password for authenticating ourselves with - * our peer using PAP. Returns 1 on success, 0 if no suitable password - * could be found. - */ -static int -get_pap_passwd(passwd) - char *passwd; -{ - char *filename; - FILE *f; - int ret; - struct wordlist *addrs; - char secret[MAXWORDLEN]; - - filename = _PATH_UPAPFILE; - addrs = NULL; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - check_access(f, filename); - ret = scan_authfile(f, user, - remote_name[0]? remote_name: NULL, - (u_int32_t)0, secret, NULL, filename); - fclose(f); - if (ret < 0) - return 0; - if (passwd != NULL) { - strncpy(passwd, secret, MAXSECRETLEN); - passwd[MAXSECRETLEN-1] = 0; - } - BZERO(secret, sizeof(secret)); - return 1; -} - - -/* - * have_pap_secret - check whether we have a PAP file with any - * secrets that we could possibly use for authenticating the peer. - */ -static int -have_pap_secret() -{ - FILE *f; - int ret; - char *filename; - ipcp_options *ipwo = &ipcp_wantoptions[0]; - u_int32_t remote; - - filename = _PATH_UPAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - ret = scan_authfile(f, NULL, our_name, remote, NULL, NULL, filename); - fclose(f); - if (ret < 0) - return 0; - - return 1; -} - - -/* - * have_chap_secret - check whether we have a CHAP file with a - * secret that we could possibly use for authenticating `client' - * on `server'. Either can be the null string, meaning we don't - * know the identity yet. - */ -static int -have_chap_secret(client, server, remote) - char *client; - char *server; - u_int32_t remote; -{ - FILE *f; - int ret; - char *filename; - - filename = _PATH_CHAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - if (client[0] == 0) - client = NULL; - else if (server[0] == 0) - server = NULL; - - ret = scan_authfile(f, client, server, remote, NULL, NULL, filename); - fclose(f); - if (ret < 0) - return 0; - - return 1; -} - - -/* - * get_secret - open the CHAP secret file and return the secret - * for authenticating the given client on the given server. - * (We could be either client or server). - */ -int -get_secret(unit, client, server, secret, secret_len, save_addrs) - int unit; - char *client; - char *server; - char *secret; - int *secret_len; - int save_addrs; -{ - FILE *f; - int ret, len; - char *filename; - struct wordlist *addrs; - char secbuf[MAXWORDLEN]; - - filename = _PATH_CHAPFILE; - addrs = NULL; - secbuf[0] = 0; - - f = fopen(filename, "r"); - if (f == NULL) { - syslog(LOG_ERR, "Can't open chap secret file %s: %m", filename); - return 0; - } - check_access(f, filename); - - ret = scan_authfile(f, client, server, (u_int32_t)0, - secbuf, &addrs, filename); - fclose(f); - if (ret < 0) - return 0; - - if (save_addrs) - set_allowed_addrs(unit, addrs); - - len = strlen(secbuf); - if (len > MAXSECRETLEN) { - syslog(LOG_ERR, "Secret for %s on %s is too long", client, server); - len = MAXSECRETLEN; - } - BCOPY(secbuf, secret, len); - BZERO(secbuf, sizeof(secbuf)); - *secret_len = len; - - return 1; -} - -/* - * set_allowed_addrs() - set the list of allowed addresses. - */ -static void -set_allowed_addrs(unit, addrs) - int unit; - struct wordlist *addrs; -{ - if (addresses[unit] != NULL) - free_wordlist(addresses[unit]); - addresses[unit] = addrs; - - /* - * If there's only one authorized address we might as well - * ask our peer for that one right away - */ - if (addrs != NULL && addrs->next == NULL) { - char *p = addrs->word; - struct ipcp_options *wo = &ipcp_wantoptions[unit]; - u_int32_t a; - struct hostent *hp; - - if (*p != '!' && *p != '-' && strchr(p, '/') == NULL) { - hp = gethostbyname(p); - if (hp != NULL && hp->h_addrtype == AF_INET) - a = *(u_int32_t *)hp->h_addr; - else - a = inet_addr(p); - if (a != (u_int32_t) -1) - wo->hisaddr = a; - } - } -} - -static void -auth_set_ip_addr(unit) - int unit; -{ - struct wordlist *addrs; - - if (non_wildclient && (addrs = addresses[unit]) != NULL) { - for (; addrs != NULL; addrs = addrs->next) { - /* Look for address overrides, and set them if we have any */ - if (strchr(addrs->word, ':') != NULL) { - if (setipaddr(addrs->word)) - break; - } - } - } -} - -/* - * auth_ip_addr - check whether the peer is authorized to use - * a given IP address. Returns 1 if authorized, 0 otherwise. - */ -int -auth_ip_addr(unit, addr) - int unit; - u_int32_t addr; -{ - return ip_addr_check(addr, addresses[unit]); -} - -static int -ip_addr_check(addr, addrs) - u_int32_t addr; - struct wordlist *addrs; -{ - int x, y; - u_int32_t a, mask, ah; - int accept; - char *ptr_word, *ptr_mask; - struct hostent *hp; - struct netent *np; - - /* don't allow loopback or multicast address */ - if (bad_ip_adrs(addr)) - return 0; - - if (addrs == NULL) - return !auth_required; /* no addresses authorized */ - - x = y = 0; - for (; addrs != NULL; addrs = addrs->next) { - y++; - /* "-" means no addresses authorized, "*" means any address allowed */ - ptr_word = addrs->word; - if (strcmp(ptr_word, "-") == 0) - break; - if (strcmp(ptr_word, "*") == 0) - return 1; - - /* - * A colon in the string means that we wish to force a specific - * local:remote address, but we ignore these for now. - */ - if (strchr(addrs->word, ':') != NULL) - x++; - else { - - accept = 1; - if (*ptr_word == '!') { - accept = 0; - ++ptr_word; - } - - mask = ~ (u_int32_t) 0; - ptr_mask = strchr (ptr_word, '/'); - if (ptr_mask != NULL) { - int bit_count; - - bit_count = (int) strtol (ptr_mask+1, (char **) 0, 10); - if (bit_count <= 0 || bit_count > 32) { - syslog (LOG_WARNING, - "invalid address length %s in auth. address list", - ptr_mask); - continue; - } - *ptr_mask = '\0'; - mask <<= 32 - bit_count; - } - - hp = gethostbyname(ptr_word); - if (hp != NULL && hp->h_addrtype == AF_INET) { - a = *(u_int32_t *)hp->h_addr; - } else { - np = getnetbyname (ptr_word); - if (np != NULL && np->n_addrtype == AF_INET) { - a = htonl (*(u_int32_t *)np->n_net); - if (ptr_mask == NULL) { - /* calculate appropriate mask for net */ - ah = ntohl(a); - if (IN_CLASSA(ah)) - mask = IN_CLASSA_NET; - else if (IN_CLASSB(ah)) - mask = IN_CLASSB_NET; - else if (IN_CLASSC(ah)) - mask = IN_CLASSC_NET; - } - } else { - a = inet_addr (ptr_word); - } - } - - if (ptr_mask != NULL) - *ptr_mask = '/'; - - if (a == (u_int32_t)-1L) - syslog (LOG_WARNING, - "unknown host %s in auth. address list", - addrs->word); - else - /* Here a and addr are in network byte order, - and mask is in host order. */ - if (((addr ^ a) & htonl(mask)) == 0) - return accept; - } /* else */ - } - return x == y; /* not in list => can't have it */ -} - -/* - * bad_ip_adrs - return 1 if the IP address is one we don't want - * to use, such as an address in the loopback net or a multicast address. - * addr is in network byte order. - */ -int -bad_ip_adrs(addr) - u_int32_t addr; -{ - addr = ntohl(addr); - return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET - || IN_MULTICAST(addr) || IN_BADCLASS(addr); -} - -/* - * check_access - complain if a secret file has too-liberal permissions. - */ -void -check_access(f, filename) - FILE *f; - char *filename; -{ - struct stat sbuf; - - if (fstat(fileno(f), &sbuf) < 0) { - syslog(LOG_WARNING, "cannot stat secret file %s: %m", filename); - } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { - syslog(LOG_WARNING, "Warning - secret file %s has world and/or group access", filename); - } -} - - -/* - * scan_authfile - Scan an authorization file for a secret suitable - * for authenticating `client' on `server'. The return value is -1 - * if no secret is found, otherwise >= 0. The return value has - * NONWILD_CLIENT set if the secret didn't have "*" for the client, and - * NONWILD_SERVER set if the secret didn't have "*" for the server. - * Any following words on the line (i.e. address authorization - * info) are placed in a wordlist and returned in *addrs. - */ -static int -scan_authfile(f, client, server, ipaddr, secret, addrs, filename) - FILE *f; - char *client; - char *server; - u_int32_t ipaddr; - char *secret; - struct wordlist **addrs; - char *filename; -{ - int newline, xxx; - int got_flag, best_flag; - FILE *sf; - struct wordlist *ap, *addr_list, *alist, *alast; - char word[MAXWORDLEN]; - char atfile[MAXWORDLEN]; - char lsecret[MAXWORDLEN]; - - if (addrs != NULL) - *addrs = NULL; - addr_list = NULL; - if (!getword(f, word, &newline, filename)) - return -1; /* file is empty??? */ - newline = 1; - best_flag = -1; - for (;;) { - /* - * Skip until we find a word at the start of a line. - */ - while (!newline && getword(f, word, &newline, filename)) - ; - if (!newline) - break; /* got to end of file */ - - /* - * Got a client - check if it's a match or a wildcard. - */ - got_flag = 0; - if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { - newline = 0; - continue; - } - if (!ISWILD(word)) - got_flag = NONWILD_CLIENT; - - /* - * Now get a server and check if it matches. - */ - if (!getword(f, word, &newline, filename)) - break; - if (newline) - continue; - if (server != NULL && strcmp(word, server) != 0 && !ISWILD(word)) - continue; - if (!ISWILD(word)) - got_flag |= NONWILD_SERVER; - - /* - * Got some sort of a match - see if it's better than what - * we have already. - */ - if (got_flag <= best_flag) - continue; - - /* - * Get the secret. - */ - if (!getword(f, word, &newline, filename)) - break; - if (newline) - continue; - - /* - * Special syntax: @filename means read secret from file. - */ - if (word[0] == '@') { - strcpy(atfile, word+1); - if ((sf = fopen(atfile, "r")) == NULL) { - syslog(LOG_WARNING, "can't open indirect secret file %s", - atfile); - continue; - } - check_access(sf, atfile); - if (!getword(sf, word, &xxx, atfile)) { - syslog(LOG_WARNING, "no secret in indirect secret file %s", - atfile); - fclose(sf); - continue; - } - fclose(sf); - } - if (secret != NULL) - strcpy(lsecret, word); - - /* - * Now read address authorization info and make a wordlist. - */ - alist = alast = NULL; - for (;;) { - if (!getword(f, word, &newline, filename) || newline) - break; - ap = (struct wordlist *) malloc(sizeof(struct wordlist) - + strlen(word)); - if (ap == NULL) - novm("authorized addresses"); - ap->next = NULL; - strcpy(ap->word, word); - if (alist == NULL) - alist = ap; - else - alast->next = ap; - alast = ap; - } - - /* - * Check if the given IP address is allowed by the wordlist. - */ - if (ipaddr != 0 && !ip_addr_check(ipaddr, alist)) { - free_wordlist(alist); - continue; - } - - /* - * This is the best so far; remember it. - */ - best_flag = got_flag; - if (addr_list) - free_wordlist(addr_list); - addr_list = alist; - if (secret != NULL) - strcpy(secret, lsecret); - - if (!newline) - break; - } - - if (addrs != NULL) - *addrs = addr_list; - else if (addr_list != NULL) - free_wordlist(addr_list); - - non_wildclient = (best_flag & NONWILD_CLIENT) && client != NULL && - *client != '\0'; - return best_flag; -} - -/* - * free_wordlist - release memory allocated for a wordlist. - */ -static void -free_wordlist(wp) - struct wordlist *wp; -{ - struct wordlist *next; - - while (wp != NULL) { - next = wp->next; - free(wp); - wp = next; - } -} - -/* - * auth_script - execute a script with arguments - * interface-name peer-name real-user tty speed - */ -static void -auth_script(script) - char *script; -{ - char strspeed[32]; - struct passwd *pw; - char struid[32]; - char *user_name; - char *argv[7]; - - if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) - user_name = pw->pw_name; - else { - sprintf(struid, "%d", getuid()); - user_name = struid; - } - sprintf(strspeed, "%d", baud_rate); - - argv[0] = script; - argv[1] = ifname; - argv[2] = peer_authname; - argv[3] = user_name; - argv[4] = devnam; - argv[5] = strspeed; - argv[6] = NULL; - - run_program(script, argv, 0); -} diff --git a/usr.sbin/pppd/cbcp.c b/usr.sbin/pppd/cbcp.c deleted file mode 100644 index 7bcfcab..0000000 --- a/usr.sbin/pppd/cbcp.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * cbcp - Call Back Configuration Protocol. - * - * Copyright (c) 1995 Pedro Roque Marques - * 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 Pedro Roque Marques. 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/time.h> -#include <syslog.h> - -#include "pppd.h" -#include "cbcp.h" -#include "fsm.h" -#include "lcp.h" -#include "ipcp.h" - -/* - * Protocol entry points. - */ -static void cbcp_init(int unit); -static void cbcp_open(int unit); -static void cbcp_lowerup(int unit); -static void cbcp_input(int unit, u_char *pkt, int len); -static void cbcp_protrej(int unit); -static int cbcp_printpkt(u_char *pkt, int len, - void (*printer)(void *, char *, ...), - void *arg); - -struct protent cbcp_protent = { - PPP_CBCP, - cbcp_init, - cbcp_input, - cbcp_protrej, - cbcp_lowerup, - NULL, - cbcp_open, - NULL, - cbcp_printpkt, - NULL, - 0, - "CBCP", - NULL, - NULL, - NULL -}; - -cbcp_state cbcp[NUM_PPP]; - -/* internal prototypes */ - -static void cbcp_recvreq(cbcp_state *us, char *pckt, int len); -static void cbcp_resp(cbcp_state *us); -static void cbcp_up(cbcp_state *us); -static void cbcp_recvack(cbcp_state *us, char *pckt, int len); -static void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len); - -/* init state */ -static void -cbcp_init(int iface) -{ - cbcp_state *us; - - us = &cbcp[iface]; - memset(us, 0, sizeof(cbcp_state)); - us->us_unit = iface; - us->us_type |= (1 << CB_CONF_NO); -} - -/* lower layer is up */ -static void -cbcp_lowerup(int iface) -{ - cbcp_state *us = &cbcp[iface]; - - syslog(LOG_DEBUG, "cbcp_lowerup"); - syslog(LOG_DEBUG, "want: %d", us->us_type); - - if (us->us_type == CB_CONF_USER) - syslog(LOG_DEBUG, "phone no: %s", us->us_number); -} - -static void -cbcp_open(int unit) -{ - syslog(LOG_DEBUG, "cbcp_open"); -} - -/* process an incomming packet */ -static void -cbcp_input(int unit, u_char *inpacket, int pktlen) -{ - u_char *inp; - u_char code, id; - u_short len; - - cbcp_state *us = &cbcp[unit]; - - inp = inpacket; - - if (pktlen < CBCP_MINLEN) { - syslog(LOG_ERR, "CBCP packet is too small"); - return; - } - - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - - if (len < CBCP_MINLEN || len > pktlen) { - syslog(LOG_ERR, "CBCP packet: invalid length"); - return; - } - - len -= CBCP_MINLEN; - - switch(code) { - case CBCP_REQ: - us->us_id = id; - cbcp_recvreq(us, inp, len); - break; - - case CBCP_RESP: - syslog(LOG_DEBUG, "CBCP_RESP received"); - break; - - case CBCP_ACK: - if (id != us->us_id) - syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d", - us->us_id, id); - - cbcp_recvack(us, inp, len); - break; - - default: - break; - } -} - -/* protocol was rejected by foe */ -void cbcp_protrej(int iface) -{ -} - -char *cbcp_codenames[] = { - "Request", "Response", "Ack" -}; - -char *cbcp_optionnames[] = { - "NoCallback", - "UserDefined", - "AdminDefined", - "List" -}; - -/* pretty print a packet */ -static int -cbcp_printpkt(u_char *p, int plen, void (*printer)(void *, char *, ...), - void *arg) -{ - int code, opt, id, len, olen, delay; - u_char *pstart; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *)) - printer(arg, " %s", cbcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - - switch (code) { - case CBCP_REQ: - case CBCP_RESP: - case CBCP_ACK: - while(len >= 2) { - GETCHAR(opt, p); - GETCHAR(olen, p); - - if (olen < 2 || olen > len) { - break; - } - - printer(arg, " <"); - len -= olen; - - if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *)) - printer(arg, " %s", cbcp_optionnames[opt-1]); - else - printer(arg, " option=0x%x", opt); - - if (olen > 2) { - GETCHAR(delay, p); - printer(arg, " delay = %d", delay); - } - - if (olen > 3) { - int addrt; - char str[256]; - - GETCHAR(addrt, p); - memcpy(str, p, olen - 4); - str[olen - 4] = 0; - printer(arg, " number = %s", str); - } - printer(arg, ">"); - break; - } - - default: - break; - } - - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} - -/* received CBCP request */ -static void -cbcp_recvreq(cbcp_state *us, char *pckt, int pcktlen) -{ - u_char type, opt_len, delay, addr_type; - char address[256]; - int len = pcktlen; - - address[0] = 0; - - while (len > 1) { - syslog(LOG_DEBUG, "length: %d", len); - - GETCHAR(type, pckt); - GETCHAR(opt_len, pckt); - - if (len < opt_len) - break; - len -= opt_len; - - if (opt_len > 2) - GETCHAR(delay, pckt); - - us->us_allowed |= (1 << type); - - switch(type) { - case CB_CONF_NO: - syslog(LOG_DEBUG, "no callback allowed"); - break; - - case CB_CONF_USER: - syslog(LOG_DEBUG, "user callback allowed"); - if (opt_len > 4) { - GETCHAR(addr_type, pckt); - memcpy(address, pckt, opt_len - 4); - address[opt_len - 4] = 0; - if (address[0]) - syslog(LOG_DEBUG, "address: %s", address); - } - break; - - case CB_CONF_ADMIN: - syslog(LOG_DEBUG, "user admin defined allowed"); - break; - - case CB_CONF_LIST: - break; - } - } - - cbcp_resp(us); -} - -static void -cbcp_resp(cbcp_state *us) -{ - u_char cb_type; - u_char buf[256]; - u_char *bufp = buf; - int len = 0; - - cb_type = us->us_allowed & us->us_type; - syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type); - -#if 0 - if (!cb_type) - lcp_down(us->us_unit); -#endif - - if (cb_type & ( 1 << CB_CONF_USER ) ) { - syslog(LOG_DEBUG, "cbcp_resp CONF_USER"); - PUTCHAR(CB_CONF_USER, bufp); - len = 3 + 1 + strlen(us->us_number) + 1; - PUTCHAR(len , bufp); - PUTCHAR(5, bufp); /* delay */ - PUTCHAR(1, bufp); - BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); - cbcp_send(us, CBCP_RESP, buf, len); - return; - } - - if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { - syslog(LOG_DEBUG, "cbcp_resp CONF_ADMIN"); - PUTCHAR(CB_CONF_ADMIN, bufp); - len = 3; - PUTCHAR(len, bufp); - PUTCHAR(5, bufp); /* delay */ - cbcp_send(us, CBCP_RESP, buf, len); - return; - } - - if (cb_type & ( 1 << CB_CONF_NO ) ) { - syslog(LOG_DEBUG, "cbcp_resp CONF_NO"); - PUTCHAR(CB_CONF_NO, bufp); - len = 2; - PUTCHAR(len , bufp); - cbcp_send(us, CBCP_RESP, buf, len); - (*ipcp_protent.open)(us->us_unit); - return; - } -} - -static void -cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len) -{ - u_char *outp; - int outlen; - - outp = outpacket_buf; - - outlen = 4 + len; - - MAKEHEADER(outp, PPP_CBCP); - - PUTCHAR(code, outp); - PUTCHAR(us->us_id, outp); - PUTSHORT(outlen, outp); - - if (len) - BCOPY(buf, outp, len); - - output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN); -} - -static void -cbcp_recvack(cbcp_state *us, char *pckt, int len) -{ - u_char type, delay, addr_type; - int opt_len; - char address[256]; - - if (len > 1) { - GETCHAR(type, pckt); - GETCHAR(opt_len, pckt); - - if (opt_len > len) - return; - - if (opt_len > 2) - GETCHAR(delay, pckt); - - if (opt_len > 4) { - GETCHAR(addr_type, pckt); - memcpy(address, pckt, opt_len - 4); - address[opt_len - 4] = 0; - if (address[0]) - syslog(LOG_DEBUG, "peer will call: %s", address); - } - } - - cbcp_up(us); -} - -extern int persist; - -/* ok peer will do callback */ -static void -cbcp_up(cbcp_state *us) -{ - persist = 0; - lcp_close(0, "Call me back, please"); -} diff --git a/usr.sbin/pppd/cbcp.h b/usr.sbin/pppd/cbcp.h deleted file mode 100644 index c2ab3f6..0000000 --- a/usr.sbin/pppd/cbcp.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef CBCP_H -#define CBCP_H - -typedef struct cbcp_state { - int us_unit; /* Interface unit number */ - u_char us_id; /* Current id */ - u_char us_allowed; - int us_type; - char *us_number; /* Telefone Number */ -} cbcp_state; - -extern cbcp_state cbcp[]; - -extern struct protent cbcp_protent; - -#define CBCP_MINLEN 4 - -#define CBCP_REQ 1 -#define CBCP_RESP 2 -#define CBCP_ACK 3 - -#define CB_CONF_NO 1 -#define CB_CONF_USER 2 -#define CB_CONF_ADMIN 3 -#define CB_CONF_LIST 4 -#endif diff --git a/usr.sbin/pppd/ccp.c b/usr.sbin/pppd/ccp.c deleted file mode 100644 index ba88135..0000000 --- a/usr.sbin/pppd/ccp.c +++ /dev/null @@ -1,1113 +0,0 @@ -/* - * ccp.c - PPP Compression Control Protocol. - * - * Copyright (c) 1994 The Australian National University. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#include <string.h> -#include <syslog.h> -#include <sys/ioctl.h> -#include <sys/types.h> - -#include "pppd.h" -#include "fsm.h" -#include "ccp.h" -#include <net/ppp_comp.h> - -/* - * Protocol entry points from main code. - */ -static void ccp_init(int unit); -static void ccp_open(int unit); -static void ccp_close(int unit, char *); -static void ccp_lowerup(int unit); -static void ccp_lowerdown(int); -static void ccp_input(int unit, u_char *pkt, int len); -static void ccp_protrej(int unit); -static int ccp_printpkt(u_char *pkt, int len, - void (*printer)(void *, char *, ...), - void *arg); -static void ccp_datainput(int unit, u_char *pkt, int len); - -struct protent ccp_protent = { - PPP_CCP, - ccp_init, - ccp_input, - ccp_protrej, - ccp_lowerup, - ccp_lowerdown, - ccp_open, - ccp_close, - ccp_printpkt, - ccp_datainput, - 1, - "CCP", - NULL, - NULL, - NULL -}; - -fsm ccp_fsm[NUM_PPP]; -ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */ -ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ -ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */ -ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */ - -/* - * Callbacks for fsm code. - */ -static void ccp_resetci(fsm *); -static int ccp_cilen(fsm *); -static void ccp_addci(fsm *, u_char *, int *); -static int ccp_ackci(fsm *, u_char *, int); -static int ccp_nakci(fsm *, u_char *, int); -static int ccp_rejci(fsm *, u_char *, int); -static int ccp_reqci(fsm *, u_char *, int *, int); -static void ccp_up(fsm *); -static void ccp_down(fsm *); -static int ccp_extcode(fsm *, int, int, u_char *, int); -static void ccp_rack_timeout(void *); -static char *method_name(ccp_options *, ccp_options *); - -static fsm_callbacks ccp_callbacks = { - ccp_resetci, - ccp_cilen, - ccp_addci, - ccp_ackci, - ccp_nakci, - ccp_rejci, - ccp_reqci, - ccp_up, - ccp_down, - NULL, - NULL, - NULL, - NULL, - ccp_extcode, - "CCP" -}; - -/* - * Do we want / did we get any compression? - */ -#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \ - || (opt).predictor_1 || (opt).predictor_2) - -/* - * Local state (mainly for handling reset-reqs and reset-acks). - */ -static int ccp_localstate[NUM_PPP]; -#define RACK_PENDING 1 /* waiting for reset-ack */ -#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ - -#define RACKTIMEOUT 1 /* second */ - -static int all_rejected[NUM_PPP]; /* we rejected all peer's options */ - -/* - * ccp_init - initialize CCP. - */ -static void -ccp_init(unit) - int unit; -{ - fsm *f = &ccp_fsm[unit]; - - f->unit = unit; - f->protocol = PPP_CCP; - f->callbacks = &ccp_callbacks; - fsm_init(f); - - memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options)); - memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options)); - memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options)); - memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options)); - - ccp_wantoptions[0].deflate = 1; - ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE; - ccp_wantoptions[0].deflate_correct = 1; - ccp_wantoptions[0].deflate_draft = 1; - ccp_allowoptions[0].deflate = 1; - ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE; - ccp_allowoptions[0].deflate_correct = 1; - ccp_allowoptions[0].deflate_draft = 1; - - ccp_wantoptions[0].bsd_compress = 1; - ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS; - ccp_allowoptions[0].bsd_compress = 1; - ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS; - - ccp_allowoptions[0].predictor_1 = 1; -} - -/* - * ccp_open - CCP is allowed to come up. - */ -static void -ccp_open(unit) - int unit; -{ - fsm *f = &ccp_fsm[unit]; - - if (f->state != OPENED) - ccp_flags_set(unit, 1, 0); - - /* - * Find out which compressors the kernel supports before - * deciding whether to open in silent mode. - */ - ccp_resetci(f); - if (!ANY_COMPRESS(ccp_gotoptions[unit])) - f->flags |= OPT_SILENT; - - fsm_open(f); -} - -/* - * ccp_close - Terminate CCP. - */ -static void -ccp_close(unit, reason) - int unit; - char *reason; -{ - ccp_flags_set(unit, 0, 0); - fsm_close(&ccp_fsm[unit], reason); -} - -/* - * ccp_lowerup - we may now transmit CCP packets. - */ -static void -ccp_lowerup(unit) - int unit; -{ - fsm_lowerup(&ccp_fsm[unit]); -} - -/* - * ccp_lowerdown - we may not transmit CCP packets. - */ -static void -ccp_lowerdown(unit) - int unit; -{ - fsm_lowerdown(&ccp_fsm[unit]); -} - -/* - * ccp_input - process a received CCP packet. - */ -static void -ccp_input(unit, p, len) - int unit; - u_char *p; - int len; -{ - fsm *f = &ccp_fsm[unit]; - int oldstate; - - /* - * Check for a terminate-request so we can print a message. - */ - oldstate = f->state; - fsm_input(f, p, len); - if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) - syslog(LOG_NOTICE, "Compression disabled by peer."); - - /* - * If we get a terminate-ack and we're not asking for compression, - * close CCP. - */ - if (oldstate == REQSENT && p[0] == TERMACK - && !ANY_COMPRESS(ccp_gotoptions[unit])) - ccp_close(unit, "No compression negotiated"); -} - -/* - * Handle a CCP-specific code. - */ -static int -ccp_extcode(f, code, id, p, len) - fsm *f; - int code, id; - u_char *p; - int len; -{ - switch (code) { - case CCP_RESETREQ: - if (f->state != OPENED) - break; - /* send a reset-ack, which the transmitter will see and - reset its compression state. */ - fsm_sdata(f, CCP_RESETACK, id, NULL, 0); - break; - - case CCP_RESETACK: - if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) { - ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT); - UNTIMEOUT(ccp_rack_timeout, f); - } - break; - - default: - return 0; - } - - return 1; -} - -/* - * ccp_protrej - peer doesn't talk CCP. - */ -static void -ccp_protrej(unit) - int unit; -{ - ccp_flags_set(unit, 0, 0); - fsm_lowerdown(&ccp_fsm[unit]); -} - -/* - * ccp_resetci - initialize at start of negotiation. - */ -static void -ccp_resetci(f) - fsm *f; -{ - ccp_options *go = &ccp_gotoptions[f->unit]; - u_char opt_buf[16]; - - *go = ccp_wantoptions[f->unit]; - all_rejected[f->unit] = 0; - - /* - * Check whether the kernel knows about the various - * compression methods we might request. - */ - if (go->bsd_compress) { - opt_buf[0] = CI_BSD_COMPRESS; - opt_buf[1] = CILEN_BSD_COMPRESS; - opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS); - if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0) - go->bsd_compress = 0; - } - if (go->deflate) { - if (go->deflate_correct) { - opt_buf[0] = CI_DEFLATE; - opt_buf[1] = CILEN_DEFLATE; - opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE); - opt_buf[3] = DEFLATE_CHK_SEQUENCE; - if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) - go->deflate_correct = 0; - } - if (go->deflate_draft) { - opt_buf[0] = CI_DEFLATE_DRAFT; - opt_buf[1] = CILEN_DEFLATE; - opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE); - opt_buf[3] = DEFLATE_CHK_SEQUENCE; - if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) - go->deflate_draft = 0; - } - if (!go->deflate_correct && !go->deflate_draft) - go->deflate = 0; - } - if (go->predictor_1) { - opt_buf[0] = CI_PREDICTOR_1; - opt_buf[1] = CILEN_PREDICTOR_1; - if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) - go->predictor_1 = 0; - } - if (go->predictor_2) { - opt_buf[0] = CI_PREDICTOR_2; - opt_buf[1] = CILEN_PREDICTOR_2; - if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) - go->predictor_2 = 0; - } -} - -/* - * ccp_cilen - Return total length of our configuration info. - */ -static int -ccp_cilen(f) - fsm *f; -{ - ccp_options *go = &ccp_gotoptions[f->unit]; - - return (go->bsd_compress? CILEN_BSD_COMPRESS: 0) - + (go->deflate? CILEN_DEFLATE: 0) - + (go->predictor_1? CILEN_PREDICTOR_1: 0) - + (go->predictor_2? CILEN_PREDICTOR_2: 0); -} - -/* - * ccp_addci - put our requests in a packet. - */ -static void -ccp_addci(f, p, lenp) - fsm *f; - u_char *p; - int *lenp; -{ - int res; - ccp_options *go = &ccp_gotoptions[f->unit]; - u_char *p0 = p; - - /* - * Add the compression types that we can receive, in decreasing - * preference order. Get the kernel to allocate the first one - * in case it gets Acked. - */ - if (go->deflate) { - p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT; - p[1] = CILEN_DEFLATE; - p[2] = DEFLATE_MAKE_OPT(go->deflate_size); - p[3] = DEFLATE_CHK_SEQUENCE; - for (;;) { - res = ccp_test(f->unit, p, CILEN_DEFLATE, 0); - if (res > 0) { - p += CILEN_DEFLATE; - break; - } - if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE) { - go->deflate = 0; - break; - } - --go->deflate_size; - p[2] = DEFLATE_MAKE_OPT(go->deflate_size); - } - if (p != p0 && go->deflate_correct && go->deflate_draft) { - p[0] = CI_DEFLATE_DRAFT; - p[1] = CILEN_DEFLATE; - p[2] = p[2 - CILEN_DEFLATE]; - p[3] = DEFLATE_CHK_SEQUENCE; - p += CILEN_DEFLATE; - } - } - if (go->bsd_compress) { - p[0] = CI_BSD_COMPRESS; - p[1] = CILEN_BSD_COMPRESS; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); - if (p != p0) { - p += CILEN_BSD_COMPRESS; /* not the first option */ - } else { - for (;;) { - res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0); - if (res > 0) { - p += CILEN_BSD_COMPRESS; - break; - } - if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) { - go->bsd_compress = 0; - break; - } - --go->bsd_bits; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); - } - } - } - /* XXX Should Predictor 2 be preferable to Predictor 1? */ - if (go->predictor_1) { - p[0] = CI_PREDICTOR_1; - p[1] = CILEN_PREDICTOR_1; - if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) { - go->predictor_1 = 0; - } else { - p += CILEN_PREDICTOR_1; - } - } - if (go->predictor_2) { - p[0] = CI_PREDICTOR_2; - p[1] = CILEN_PREDICTOR_2; - if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) { - go->predictor_2 = 0; - } else { - p += CILEN_PREDICTOR_2; - } - } - - go->method = (p > p0)? p0[0]: -1; - - *lenp = p - p0; -} - -/* - * ccp_ackci - process a received configure-ack, and return - * 1 iff the packet was OK. - */ -static int -ccp_ackci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ccp_options *go = &ccp_gotoptions[f->unit]; - u_char *p0 = p; - - if (go->deflate) { - if (len < CILEN_DEFLATE - || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) - || p[1] != CILEN_DEFLATE - || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - /* XXX Cope with first/fast ack */ - if (len == 0) - return 1; - if (go->deflate_correct && go->deflate_draft) { - if (len < CILEN_DEFLATE - || p[0] != CI_DEFLATE_DRAFT - || p[1] != CILEN_DEFLATE - || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - } - if (go->bsd_compress) { - if (len < CILEN_BSD_COMPRESS - || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS - || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) - return 0; - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } - if (go->predictor_1) { - if (len < CILEN_PREDICTOR_1 - || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) - return 0; - p += CILEN_PREDICTOR_1; - len -= CILEN_PREDICTOR_1; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } - if (go->predictor_2) { - if (len < CILEN_PREDICTOR_2 - || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) - return 0; - p += CILEN_PREDICTOR_2; - len -= CILEN_PREDICTOR_2; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } - - if (len != 0) - return 0; - return 1; -} - -/* - * ccp_nakci - process received configure-nak. - * Returns 1 iff the nak was OK. - */ -static int -ccp_nakci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ccp_options *go = &ccp_gotoptions[f->unit]; - ccp_options no; /* options we've seen already */ - ccp_options try; /* options to ask for next time */ - - memset(&no, 0, sizeof(no)); - try = *go; - - if (go->deflate && len >= CILEN_DEFLATE - && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) - && p[1] == CILEN_DEFLATE) { - no.deflate = 1; - /* - * Peer wants us to use a different code size or something. - * Stop asking for Deflate if we don't understand his suggestion. - */ - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL - || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_SIZE - || p[3] != DEFLATE_CHK_SEQUENCE) - try.deflate = 0; - else if (DEFLATE_SIZE(p[2]) < go->deflate_size) - try.deflate_size = DEFLATE_SIZE(p[2]); - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - if (go->deflate_correct && go->deflate_draft - && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT - && p[1] == CILEN_DEFLATE) { - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - } - - if (go->bsd_compress && len >= CILEN_BSD_COMPRESS - && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { - no.bsd_compress = 1; - /* - * Peer wants us to use a different number of bits - * or a different version. - */ - if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) - try.bsd_compress = 0; - else if (BSD_NBITS(p[2]) < go->bsd_bits) - try.bsd_bits = BSD_NBITS(p[2]); - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - } - - /* - * Predictor-1 and 2 have no options, so they can't be Naked. - * - * XXX What should we do with any remaining options? - */ - - if (len != 0) - return 0; - - if (f->state != OPENED) - *go = try; - return 1; -} - -/* - * ccp_rejci - reject some of our suggested compression methods. - */ -static int -ccp_rejci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ccp_options *go = &ccp_gotoptions[f->unit]; - ccp_options try; /* options to request next time */ - - try = *go; - - /* - * Cope with empty configure-rejects by ceasing to send - * configure-requests. - */ - if (len == 0 && all_rejected[f->unit]) - return -1; - - if (go->deflate && len >= CILEN_DEFLATE - && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) - && p[1] == CILEN_DEFLATE) { - if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; /* Rej is bad */ - if (go->deflate_correct) - try.deflate_correct = 0; - else - try.deflate_draft = 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - if (go->deflate_correct && go->deflate_draft - && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT - && p[1] == CILEN_DEFLATE) { - if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; /* Rej is bad */ - try.deflate_draft = 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - if (!try.deflate_correct && !try.deflate_draft) - try.deflate = 0; - } - if (go->bsd_compress && len >= CILEN_BSD_COMPRESS - && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { - if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) - return 0; - try.bsd_compress = 0; - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - } - if (go->predictor_1 && len >= CILEN_PREDICTOR_1 - && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { - try.predictor_1 = 0; - p += CILEN_PREDICTOR_1; - len -= CILEN_PREDICTOR_1; - } - if (go->predictor_2 && len >= CILEN_PREDICTOR_2 - && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { - try.predictor_2 = 0; - p += CILEN_PREDICTOR_2; - len -= CILEN_PREDICTOR_2; - } - - if (len != 0) - return 0; - - if (f->state != OPENED) - *go = try; - - return 1; -} - -/* - * ccp_reqci - processed a received configure-request. - * Returns CONFACK, CONFNAK or CONFREJ and the packet modified - * appropriately. - */ -static int -ccp_reqci(f, p, lenp, dont_nak) - fsm *f; - u_char *p; - int *lenp; - int dont_nak; -{ - int ret, newret, res; - u_char *p0, *retp; - int len, clen, type, nb; - ccp_options *ho = &ccp_hisoptions[f->unit]; - ccp_options *ao = &ccp_allowoptions[f->unit]; - - ret = CONFACK; - retp = p0 = p; - len = *lenp; - - memset(ho, 0, sizeof(ccp_options)); - ho->method = (len > 0)? p[0]: -1; - - while (len > 0) { - newret = CONFACK; - if (len < 2 || p[1] < 2 || p[1] > len) { - /* length is bad */ - clen = len; - newret = CONFREJ; - - } else { - type = p[0]; - clen = p[1]; - - switch (type) { - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (!ao->deflate || clen != CILEN_DEFLATE - || (!ao->deflate_correct && type == CI_DEFLATE) - || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { - newret = CONFREJ; - break; - } - - ho->deflate = 1; - ho->deflate_size = nb = DEFLATE_SIZE(p[2]); - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL - || p[3] != DEFLATE_CHK_SEQUENCE - || nb > ao->deflate_size || nb < DEFLATE_MIN_SIZE) { - newret = CONFNAK; - if (!dont_nak) { - p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); - p[3] = DEFLATE_CHK_SEQUENCE; - /* fall through to test this #bits below */ - } else - break; - } - - /* - * Check whether we can do Deflate with the window - * size they want. If the window is too big, reduce - * it until the kernel can cope and nak with that. - * We only check this for the first option. - */ - if (p == p0) { - for (;;) { - res = ccp_test(f->unit, p, CILEN_DEFLATE, 1); - if (res > 0) - break; /* it's OK now */ - if (res < 0 || nb == DEFLATE_MIN_SIZE || dont_nak) { - newret = CONFREJ; - p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); - break; - } - newret = CONFNAK; - --nb; - p[2] = DEFLATE_MAKE_OPT(nb); - } - } - break; - - case CI_BSD_COMPRESS: - if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { - newret = CONFREJ; - break; - } - - ho->bsd_compress = 1; - ho->bsd_bits = nb = BSD_NBITS(p[2]); - if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION - || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { - newret = CONFNAK; - if (!dont_nak) { - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); - /* fall through to test this #bits below */ - } else - break; - } - - /* - * Check whether we can do BSD-Compress with the code - * size they want. If the code size is too big, reduce - * it until the kernel can cope and nak with that. - * We only check this for the first option. - */ - if (p == p0) { - for (;;) { - res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1); - if (res > 0) - break; - if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { - newret = CONFREJ; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, - ho->bsd_bits); - break; - } - newret = CONFNAK; - --nb; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); - } - } - break; - - case CI_PREDICTOR_1: - if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { - newret = CONFREJ; - break; - } - - ho->predictor_1 = 1; - if (p == p0 - && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) { - newret = CONFREJ; - } - break; - - case CI_PREDICTOR_2: - if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { - newret = CONFREJ; - break; - } - - ho->predictor_2 = 1; - if (p == p0 - && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) { - newret = CONFREJ; - } - break; - - default: - newret = CONFREJ; - } - } - - if (newret == CONFNAK && dont_nak) - newret = CONFREJ; - if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { - /* we're returning this option */ - if (newret == CONFREJ && ret == CONFNAK) - retp = p0; - ret = newret; - if (p != retp) - BCOPY(p, retp, clen); - retp += clen; - } - - p += clen; - len -= clen; - } - - if (ret != CONFACK) { - if (ret == CONFREJ && *lenp == retp - p0) - all_rejected[f->unit] = 1; - else - *lenp = retp - p0; - } - return ret; -} - -/* - * Make a string name for a compression method (or 2). - */ -static char * -method_name(opt, opt2) - ccp_options *opt, *opt2; -{ - static char result[64]; - - if (!ANY_COMPRESS(*opt)) - return "(none)"; - switch (opt->method) { - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) - sprintf(result, "Deflate%s (%d/%d)", - (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), - opt->deflate_size, opt2->deflate_size); - else - sprintf(result, "Deflate%s (%d)", - (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), - opt->deflate_size); - break; - case CI_BSD_COMPRESS: - if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) - sprintf(result, "BSD-Compress (%d/%d)", opt->bsd_bits, - opt2->bsd_bits); - else - sprintf(result, "BSD-Compress (%d)", opt->bsd_bits); - break; - case CI_PREDICTOR_1: - return "Predictor 1"; - case CI_PREDICTOR_2: - return "Predictor 2"; - default: - sprintf(result, "Method %d", opt->method); - } - return result; -} - -/* - * CCP has come up - inform the kernel driver and log a message. - */ -static void -ccp_up(f) - fsm *f; -{ - ccp_options *go = &ccp_gotoptions[f->unit]; - ccp_options *ho = &ccp_hisoptions[f->unit]; - char method1[64]; - - ccp_flags_set(f->unit, 1, 1); - if (ANY_COMPRESS(*go)) { - if (ANY_COMPRESS(*ho)) { - if (go->method == ho->method) { - syslog(LOG_NOTICE, "%s compression enabled", - method_name(go, ho)); - } else { - strcpy(method1, method_name(go, NULL)); - syslog(LOG_NOTICE, "%s / %s compression enabled", - method1, method_name(ho, NULL)); - } - } else - syslog(LOG_NOTICE, "%s receive compression enabled", - method_name(go, NULL)); - } else if (ANY_COMPRESS(*ho)) - syslog(LOG_NOTICE, "%s transmit compression enabled", - method_name(ho, NULL)); -} - -/* - * CCP has gone down - inform the kernel driver. - */ -static void -ccp_down(f) - fsm *f; -{ - if (ccp_localstate[f->unit] & RACK_PENDING) - UNTIMEOUT(ccp_rack_timeout, f); - ccp_localstate[f->unit] = 0; - ccp_flags_set(f->unit, 1, 0); -} - -/* - * Print the contents of a CCP packet. - */ -static char *ccp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej", - NULL, NULL, NULL, NULL, NULL, NULL, - "ResetReq", "ResetAck", -}; - -static int -ccp_printpkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer)(void *, char *, ...); - void *arg; -{ - u_char *p0, *optend; - int code, id, len; - int optlen; - - p0 = p; - if (plen < HEADERLEN) - return 0; - code = p[0]; - id = p[1]; - len = (p[2] << 8) + p[3]; - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *) - && ccp_codenames[code-1] != NULL) - printer(arg, " %s", ccp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - p += HEADERLEN; - - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print list of possible compression methods */ - while (len >= 2) { - code = p[0]; - optlen = p[1]; - if (optlen < 2 || optlen > len) - break; - printer(arg, " <"); - len -= optlen; - optend = p + optlen; - switch (code) { - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (optlen >= CILEN_DEFLATE) { - printer(arg, "deflate%s %d", - (code == CI_DEFLATE_DRAFT? "(old#)": ""), - DEFLATE_SIZE(p[2])); - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) - printer(arg, " method %d", DEFLATE_METHOD(p[2])); - if (p[3] != DEFLATE_CHK_SEQUENCE) - printer(arg, " check %d", p[3]); - p += CILEN_DEFLATE; - } - break; - case CI_BSD_COMPRESS: - if (optlen >= CILEN_BSD_COMPRESS) { - printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), - BSD_NBITS(p[2])); - p += CILEN_BSD_COMPRESS; - } - break; - case CI_PREDICTOR_1: - if (optlen >= CILEN_PREDICTOR_1) { - printer(arg, "predictor 1"); - p += CILEN_PREDICTOR_1; - } - break; - case CI_PREDICTOR_2: - if (optlen >= CILEN_PREDICTOR_2) { - printer(arg, "predictor 2"); - p += CILEN_PREDICTOR_2; - } - break; - } - while (p < optend) - printer(arg, " %.2x", *p++); - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - } - - /* dump out the rest of the packet in hex */ - while (--len >= 0) - printer(arg, " %.2x", *p++); - - return p - p0; -} - -/* - * We have received a packet that the decompressor failed to - * decompress. Here we would expect to issue a reset-request, but - * Motorola has a patent on resetting the compressor as a result of - * detecting an error in the decompressed data after decompression. - * (See US patent 5,130,993; international patent publication number - * WO 91/10289; Australian patent 73296/91.) - * - * So we ask the kernel whether the error was detected after - * decompression; if it was, we take CCP down, thus disabling - * compression :-(, otherwise we issue the reset-request. - */ -static void -ccp_datainput(unit, pkt, len) - int unit; - u_char *pkt; - int len; -{ - fsm *f; - - f = &ccp_fsm[unit]; - if (f->state == OPENED) { - if (ccp_fatal_error(unit)) { - /* - * Disable compression by taking CCP down. - */ - syslog(LOG_ERR, "Lost compression sync: disabling compression"); - ccp_close(unit, "Lost compression sync"); - } else { - /* - * Send a reset-request to reset the peer's compressor. - * We don't do that if we are still waiting for an - * acknowledgement to a previous reset-request. - */ - if (!(ccp_localstate[f->unit] & RACK_PENDING)) { - fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - ccp_localstate[f->unit] |= RACK_PENDING; - } else - ccp_localstate[f->unit] |= RREQ_REPEAT; - } - } -} - -/* - * Timeout waiting for reset-ack. - */ -static void -ccp_rack_timeout(arg) - void *arg; -{ - fsm *f = arg; - - if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) { - fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - ccp_localstate[f->unit] &= ~RREQ_REPEAT; - } else - ccp_localstate[f->unit] &= ~RACK_PENDING; -} - diff --git a/usr.sbin/pppd/ccp.h b/usr.sbin/pppd/ccp.h deleted file mode 100644 index a03ac4d..0000000 --- a/usr.sbin/pppd/ccp.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ccp.h - Definitions for PPP Compression Control Protocol. - * - * Copyright (c) 1994 The Australian National University. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - * - * $FreeBSD$ - */ - -typedef struct ccp_options { - u_int bsd_compress: 1; /* do BSD Compress? */ - u_int deflate: 1; /* do Deflate? (RFC code) */ - u_int baddeflate: 1; /* do Deflate? (Magnalink!) */ - u_int predictor_1: 1; /* do Predictor-1? */ - u_int predictor_2: 1; /* do Predictor-2? */ - u_int deflate_correct: 1; /* use correct code for deflate? */ - u_int deflate_draft: 1; /* use draft RFC code for deflate? */ - u_short bsd_bits; /* # bits/code for BSD Compress */ - u_short deflate_size; /* lg(window size) for Deflate */ - u_short baddeflate_size; /* lg(window size) for Deflate */ - short method; /* code for chosen compression method */ -} ccp_options; - -extern fsm ccp_fsm[]; -extern ccp_options ccp_wantoptions[]; -extern ccp_options ccp_gotoptions[]; -extern ccp_options ccp_allowoptions[]; -extern ccp_options ccp_hisoptions[]; - -extern struct protent ccp_protent; diff --git a/usr.sbin/pppd/chap.c b/usr.sbin/pppd/chap.c deleted file mode 100644 index 055dc7b..0000000 --- a/usr.sbin/pppd/chap.c +++ /dev/null @@ -1,870 +0,0 @@ -/* - * chap.c - Challenge Handshake Authentication Protocol. - * - * Copyright (c) 1993 The Australian National 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 the Australian National 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. - * - * Copyright (c) 1991 Gregory M. Christy. - * 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 Gregory M. Christy. 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -/* - * TODO: - */ - -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/time.h> -#include <syslog.h> -#include <md5.h> - -#include "pppd.h" -#include "chap.h" -#include "md5.h" -#ifdef CHAPMS -#include "chap_ms.h" -#endif - -/* - * Protocol entry points. - */ -static void ChapInit(int); -static void ChapLowerUp(int); -static void ChapLowerDown(int); -static void ChapInput(int, u_char *, int); -static void ChapProtocolReject(int); -static int ChapPrintPkt(u_char *, int, - void (*)(void *, char *, ...), void *); - -struct protent chap_protent = { - PPP_CHAP, - ChapInit, - ChapInput, - ChapProtocolReject, - ChapLowerUp, - ChapLowerDown, - NULL, - NULL, - ChapPrintPkt, - NULL, - 1, - "CHAP", - NULL, - NULL, - NULL -}; - -chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ - -static void ChapChallengeTimeout(void *); -static void ChapResponseTimeout(void *); -static void ChapReceiveChallenge(chap_state *, u_char *, int, int); -static void ChapRechallenge(void *); -static void ChapReceiveResponse(chap_state *, u_char *, int, int); -static void ChapReceiveSuccess(chap_state *, u_char *, int, int); -static void ChapReceiveFailure(chap_state *, u_char *, int, int); -static void ChapSendStatus(chap_state *, int); -static void ChapSendChallenge(chap_state *); -static void ChapSendResponse(chap_state *); -static void ChapGenChallenge(chap_state *); - -extern double drand48(void); -extern void srand48(long); - -/* - * ChapInit - Initialize a CHAP unit. - */ -static void -ChapInit(unit) - int unit; -{ - chap_state *cstate = &chap[unit]; - - BZERO(cstate, sizeof(*cstate)); - cstate->unit = unit; - cstate->clientstate = CHAPCS_INITIAL; - cstate->serverstate = CHAPSS_INITIAL; - cstate->timeouttime = CHAP_DEFTIMEOUT; - cstate->max_transmits = CHAP_DEFTRANSMITS; - /* random number generator is initialized in magic_init */ -} - - -/* - * ChapAuthWithPeer - Authenticate us with our peer (start client). - * - */ -void -ChapAuthWithPeer(unit, our_name, digest) - int unit; - char *our_name; - int digest; -{ - chap_state *cstate = &chap[unit]; - - cstate->resp_name = our_name; - cstate->resp_type = digest; - - if (cstate->clientstate == CHAPCS_INITIAL || - cstate->clientstate == CHAPCS_PENDING) { - /* lower layer isn't up - wait until later */ - cstate->clientstate = CHAPCS_PENDING; - return; - } - - /* - * We get here as a result of LCP coming up. - * So even if CHAP was open before, we will - * have to re-authenticate ourselves. - */ - cstate->clientstate = CHAPCS_LISTEN; -} - - -/* - * ChapAuthPeer - Authenticate our peer (start server). - */ -void -ChapAuthPeer(unit, our_name, digest) - int unit; - char *our_name; - int digest; -{ - chap_state *cstate = &chap[unit]; - - cstate->chal_name = our_name; - cstate->chal_type = digest; - - if (cstate->serverstate == CHAPSS_INITIAL || - cstate->serverstate == CHAPSS_PENDING) { - /* lower layer isn't up - wait until later */ - cstate->serverstate = CHAPSS_PENDING; - return; - } - - ChapGenChallenge(cstate); - ChapSendChallenge(cstate); /* crank it up dude! */ - cstate->serverstate = CHAPSS_INITIAL_CHAL; -} - - -/* - * ChapChallengeTimeout - Timeout expired on sending challenge. - */ -static void -ChapChallengeTimeout(arg) - void *arg; -{ - chap_state *cstate = (chap_state *) arg; - - /* if we aren't sending challenges, don't worry. then again we */ - /* probably shouldn't be here either */ - if (cstate->serverstate != CHAPSS_INITIAL_CHAL && - cstate->serverstate != CHAPSS_RECHALLENGE) - return; - - if (cstate->chal_transmits >= cstate->max_transmits) { - /* give up on peer */ - syslog(LOG_ERR, "Peer failed to respond to CHAP challenge"); - cstate->serverstate = CHAPSS_BADAUTH; - auth_peer_fail(cstate->unit, PPP_CHAP); - return; - } - - ChapSendChallenge(cstate); /* Re-send challenge */ -} - - -/* - * ChapResponseTimeout - Timeout expired on sending response. - */ -static void -ChapResponseTimeout(arg) - void *arg; -{ - chap_state *cstate = (chap_state *) arg; - - /* if we aren't sending a response, don't worry. */ - if (cstate->clientstate != CHAPCS_RESPONSE) - return; - - ChapSendResponse(cstate); /* re-send response */ -} - - -/* - * ChapRechallenge - Time to challenge the peer again. - */ -static void -ChapRechallenge(arg) - void *arg; -{ - chap_state *cstate = (chap_state *) arg; - - /* if we aren't sending a response, don't worry. */ - if (cstate->serverstate != CHAPSS_OPEN) - return; - - ChapGenChallenge(cstate); - ChapSendChallenge(cstate); - cstate->serverstate = CHAPSS_RECHALLENGE; -} - - -/* - * ChapLowerUp - The lower layer is up. - * - * Start up if we have pending requests. - */ -static void -ChapLowerUp(unit) - int unit; -{ - chap_state *cstate = &chap[unit]; - - if (cstate->clientstate == CHAPCS_INITIAL) - cstate->clientstate = CHAPCS_CLOSED; - else if (cstate->clientstate == CHAPCS_PENDING) - cstate->clientstate = CHAPCS_LISTEN; - - if (cstate->serverstate == CHAPSS_INITIAL) - cstate->serverstate = CHAPSS_CLOSED; - else if (cstate->serverstate == CHAPSS_PENDING) { - ChapGenChallenge(cstate); - ChapSendChallenge(cstate); - cstate->serverstate = CHAPSS_INITIAL_CHAL; - } -} - - -/* - * ChapLowerDown - The lower layer is down. - * - * Cancel all timeouts. - */ -static void -ChapLowerDown(unit) - int unit; -{ - chap_state *cstate = &chap[unit]; - - /* Timeout(s) pending? Cancel if so. */ - if (cstate->serverstate == CHAPSS_INITIAL_CHAL || - cstate->serverstate == CHAPSS_RECHALLENGE) - UNTIMEOUT(ChapChallengeTimeout, cstate); - else if (cstate->serverstate == CHAPSS_OPEN - && cstate->chal_interval != 0) - UNTIMEOUT(ChapRechallenge, cstate); - if (cstate->clientstate == CHAPCS_RESPONSE) - UNTIMEOUT(ChapResponseTimeout, cstate); - - cstate->clientstate = CHAPCS_INITIAL; - cstate->serverstate = CHAPSS_INITIAL; -} - - -/* - * ChapProtocolReject - Peer doesn't grok CHAP. - */ -static void -ChapProtocolReject(unit) - int unit; -{ - chap_state *cstate = &chap[unit]; - - if (cstate->serverstate != CHAPSS_INITIAL && - cstate->serverstate != CHAPSS_CLOSED) - auth_peer_fail(unit, PPP_CHAP); - if (cstate->clientstate != CHAPCS_INITIAL && - cstate->clientstate != CHAPCS_CLOSED) - auth_withpeer_fail(unit, PPP_CHAP); - ChapLowerDown(unit); /* shutdown chap */ -} - - -/* - * ChapInput - Input CHAP packet. - */ -static void -ChapInput(unit, inpacket, packet_len) - int unit; - u_char *inpacket; - int packet_len; -{ - chap_state *cstate = &chap[unit]; - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (packet_len < CHAP_HEADERLEN) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < CHAP_HEADERLEN) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.")); - return; - } - if (len > packet_len) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.")); - return; - } - len -= CHAP_HEADERLEN; - - /* - * Action depends on code (as in fact it usually does :-). - */ - switch (code) { - case CHAP_CHALLENGE: - ChapReceiveChallenge(cstate, inp, id, len); - break; - - case CHAP_RESPONSE: - ChapReceiveResponse(cstate, inp, id, len); - break; - - case CHAP_FAILURE: - ChapReceiveFailure(cstate, inp, id, len); - break; - - case CHAP_SUCCESS: - ChapReceiveSuccess(cstate, inp, id, len); - break; - - default: /* Need code reject? */ - syslog(LOG_WARNING, "Unknown CHAP code (%d) received.", code); - break; - } -} - - -/* - * ChapReceiveChallenge - Receive Challenge and send Response. - */ -static void -ChapReceiveChallenge(cstate, inp, id, len) - chap_state *cstate; - u_char *inp; - int id; - int len; -{ - int rchallenge_len; - u_char *rchallenge; - int secret_len; - char secret[MAXSECRETLEN]; - char rhostname[256]; - MD5_CTX mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; - - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.", id)); - if (cstate->clientstate == CHAPCS_CLOSED || - cstate->clientstate == CHAPCS_PENDING) { - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d", - cstate->clientstate)); - return; - } - - if (len < 2) { - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.")); - return; - } - - GETCHAR(rchallenge_len, inp); - len -= sizeof (u_char) + rchallenge_len; /* now name field length */ - if (len < 0) { - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.")); - return; - } - rchallenge = inp; - INCPTR(rchallenge_len, inp); - - if (len >= sizeof(rhostname)) - len = sizeof(rhostname) - 1; - BCOPY(inp, rhostname, len); - rhostname[len] = '\000'; - - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'", - rhostname)); - - /* Microsoft doesn't send their name back in the PPP packet */ - if (remote_name[0] != 0 && (explicit_remote || rhostname[0] == 0)) { - strncpy(rhostname, remote_name, sizeof(rhostname)); - rhostname[sizeof(rhostname) - 1] = 0; - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name", - rhostname)); - } - - /* get secret for authenticating ourselves with the specified host */ - if (!get_secret(cstate->unit, cstate->resp_name, rhostname, - secret, &secret_len, 0)) { - secret_len = 0; /* assume null secret if can't find one */ - syslog(LOG_WARNING, "No CHAP secret found for authenticating us to %s", - rhostname); - } - - /* cancel response send timeout if necessary */ - if (cstate->clientstate == CHAPCS_RESPONSE) - UNTIMEOUT(ChapResponseTimeout, cstate); - - cstate->resp_id = id; - cstate->resp_transmits = 0; - - /* generate MD based on negotiated type */ - switch (cstate->resp_type) { - - case CHAP_DIGEST_MD5: - MD5Init(&mdContext); - MD5Update(&mdContext, &cstate->resp_id, 1); - MD5Update(&mdContext, secret, secret_len); - MD5Update(&mdContext, rchallenge, rchallenge_len); - MD5Final(hash, &mdContext); - BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE); - cstate->resp_length = MD5_SIGNATURE_SIZE; - break; - -#ifdef CHAPMS - case CHAP_MICROSOFT: - ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); - break; -#endif - - default: - CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type)); - return; - } - - BZERO(secret, sizeof(secret)); - ChapSendResponse(cstate); -} - - -/* - * ChapReceiveResponse - Receive and process response. - */ -static void -ChapReceiveResponse(cstate, inp, id, len) - chap_state *cstate; - u_char *inp; - int id; - int len; -{ - u_char *remmd, remmd_len; - int secret_len, old_state; - int code; - char rhostname[256]; - MD5_CTX mdContext; - char secret[MAXSECRETLEN]; - u_char hash[MD5_SIGNATURE_SIZE]; - - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.", id)); - - if (cstate->serverstate == CHAPSS_CLOSED || - cstate->serverstate == CHAPSS_PENDING) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d", - cstate->serverstate)); - return; - } - - if (id != cstate->chal_id) - return; /* doesn't match ID of last challenge */ - - /* - * If we have received a duplicate or bogus Response, - * we have to send the same answer (Success/Failure) - * as we did for the first Response we saw. - */ - if (cstate->serverstate == CHAPSS_OPEN) { - ChapSendStatus(cstate, CHAP_SUCCESS); - return; - } - if (cstate->serverstate == CHAPSS_BADAUTH) { - ChapSendStatus(cstate, CHAP_FAILURE); - return; - } - - if (len < 2) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.")); - return; - } - GETCHAR(remmd_len, inp); /* get length of MD */ - remmd = inp; /* get pointer to MD */ - INCPTR(remmd_len, inp); - - len -= sizeof (u_char) + remmd_len; - if (len < 0) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.")); - return; - } - - UNTIMEOUT(ChapChallengeTimeout, cstate); - - if (len >= sizeof(rhostname)) - len = sizeof(rhostname) - 1; - BCOPY(inp, rhostname, len); - rhostname[len] = '\000'; - - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s", - rhostname)); - - /* - * Get secret for authenticating them with us, - * do the hash ourselves, and compare the result. - */ - code = CHAP_FAILURE; - if (!get_secret(cstate->unit, rhostname, cstate->chal_name, - secret, &secret_len, 1)) { - syslog(LOG_WARNING, "No CHAP secret found for authenticating %s", - rhostname); - } else { - - /* generate MD based on negotiated type */ - switch (cstate->chal_type) { - - case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ - if (remmd_len != MD5_SIGNATURE_SIZE) - break; /* it's not even the right length */ - MD5Init(&mdContext); - MD5Update(&mdContext, &cstate->chal_id, 1); - MD5Update(&mdContext, secret, secret_len); - MD5Update(&mdContext, cstate->challenge, cstate->chal_len); - MD5Final(hash, &mdContext); - - /* compare local and remote MDs and send the appropriate status */ - if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) - code = CHAP_SUCCESS; /* they are the same! */ - break; - - default: - CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->chal_type)); - } - } - - BZERO(secret, sizeof(secret)); - ChapSendStatus(cstate, code); - - if (code == CHAP_SUCCESS) { - old_state = cstate->serverstate; - cstate->serverstate = CHAPSS_OPEN; - if (old_state == CHAPSS_INITIAL_CHAL) { - auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len); - } - if (cstate->chal_interval != 0) - TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); - syslog(LOG_NOTICE, "CHAP peer authentication succeeded for %s", - rhostname); - - } else { - syslog(LOG_ERR, "CHAP peer authentication failed for remote host %s", - rhostname); - cstate->serverstate = CHAPSS_BADAUTH; - auth_peer_fail(cstate->unit, PPP_CHAP); - } -} - -/* - * ChapReceiveSuccess - Receive Success - */ -static void -ChapReceiveSuccess(cstate, inp, id, len) - chap_state *cstate; - u_char *inp; - u_char id; - int len; -{ - - CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.", id)); - - if (cstate->clientstate == CHAPCS_OPEN) - /* presumably an answer to a duplicate response */ - return; - - if (cstate->clientstate != CHAPCS_RESPONSE) { - /* don't know what this is */ - CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n", - cstate->clientstate)); - return; - } - - UNTIMEOUT(ChapResponseTimeout, cstate); - - /* - * Print message. - */ - if (len > 0) - PRINTMSG(inp, len); - - cstate->clientstate = CHAPCS_OPEN; - - auth_withpeer_success(cstate->unit, PPP_CHAP); -} - - -/* - * ChapReceiveFailure - Receive failure. - */ -static void -ChapReceiveFailure(cstate, inp, id, len) - chap_state *cstate; - u_char *inp; - u_char id; - int len; -{ - CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.", id)); - - if (cstate->clientstate != CHAPCS_RESPONSE) { - /* don't know what this is */ - CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n", - cstate->clientstate)); - return; - } - - UNTIMEOUT(ChapResponseTimeout, cstate); - - /* - * Print message. - */ - if (len > 0) - PRINTMSG(inp, len); - - syslog(LOG_ERR, "CHAP authentication failed"); - auth_withpeer_fail(cstate->unit, PPP_CHAP); -} - - -/* - * ChapSendChallenge - Send an Authenticate challenge. - */ -static void -ChapSendChallenge(cstate) - chap_state *cstate; -{ - u_char *outp; - int chal_len, name_len; - int outlen; - - chal_len = cstate->chal_len; - name_len = strlen(cstate->chal_name); - outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; - outp = outpacket_buf; - - MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ - - PUTCHAR(CHAP_CHALLENGE, outp); - PUTCHAR(cstate->chal_id, outp); - PUTSHORT(outlen, outp); - - PUTCHAR(chal_len, outp); /* put length of challenge */ - BCOPY(cstate->challenge, outp, chal_len); - INCPTR(chal_len, outp); - - BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ - - output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); - - CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.", cstate->chal_id)); - - TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime); - ++cstate->chal_transmits; -} - - -/* - * ChapSendStatus - Send a status response (ack or nak). - */ -static void -ChapSendStatus(cstate, code) - chap_state *cstate; - int code; -{ - u_char *outp; - int outlen, msglen; - char msg[256]; - - if (code == CHAP_SUCCESS) - sprintf(msg, "Welcome to %s.", hostname); - else - sprintf(msg, "I don't like you. Go 'way."); - msglen = strlen(msg); - - outlen = CHAP_HEADERLEN + msglen; - outp = outpacket_buf; - - MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ - - PUTCHAR(code, outp); - PUTCHAR(cstate->chal_id, outp); - PUTSHORT(outlen, outp); - BCOPY(msg, outp, msglen); - output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); - - CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.", code, - cstate->chal_id)); -} - -/* - * ChapGenChallenge is used to generate a pseudo-random challenge string of - * a pseudo-random length between min_len and max_len. The challenge - * string and its length are stored in *cstate, and various other fields of - * *cstate are initialized. - */ - -static void -ChapGenChallenge(cstate) - chap_state *cstate; -{ - int chal_len; - u_char *ptr = cstate->challenge; - unsigned int i; - - /* pick a random challenge length between MIN_CHALLENGE_LENGTH and - MAX_CHALLENGE_LENGTH */ - chal_len = (unsigned) ((drand48() * - (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) + - MIN_CHALLENGE_LENGTH); - cstate->chal_len = chal_len; - cstate->chal_id = ++cstate->id; - cstate->chal_transmits = 0; - - /* generate a random string */ - for (i = 0; i < chal_len; i++ ) - *ptr++ = (char) (drand48() * 0xff); -} - -/* - * ChapSendResponse - send a response packet with values as specified - * in *cstate. - */ -/* ARGSUSED */ -static void -ChapSendResponse(cstate) - chap_state *cstate; -{ - u_char *outp; - int outlen, md_len, name_len; - - md_len = cstate->resp_length; - name_len = strlen(cstate->resp_name); - outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; - outp = outpacket_buf; - - MAKEHEADER(outp, PPP_CHAP); - - PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ - PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ - PUTSHORT(outlen, outp); /* packet length */ - - PUTCHAR(md_len, outp); /* length of MD */ - BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ - INCPTR(md_len, outp); - - BCOPY(cstate->resp_name, outp, name_len); /* append our name */ - - /* send the packet */ - output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); - - cstate->clientstate = CHAPCS_RESPONSE; - TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime); - ++cstate->resp_transmits; -} - -/* - * ChapPrintPkt - print the contents of a CHAP packet. - */ -static char *ChapCodenames[] = { - "Challenge", "Response", "Success", "Failure" -}; - -static int -ChapPrintPkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer)(void *, char *, ...); - void *arg; -{ - int code, id, len; - int clen, nlen; - u_char x; - - if (plen < CHAP_HEADERLEN) - return 0; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < CHAP_HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) - printer(arg, " %s", ChapCodenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= CHAP_HEADERLEN; - switch (code) { - case CHAP_CHALLENGE: - case CHAP_RESPONSE: - if (len < 1) - break; - clen = p[0]; - if (len < clen + 1) - break; - ++p; - nlen = len - clen - 1; - printer(arg, " <"); - for (; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, "%.2x", x); - } - printer(arg, ">, name = "); - print_string((char *)p, nlen, printer, arg); - break; - case CHAP_FAILURE: - case CHAP_SUCCESS: - printer(arg, " "); - print_string((char *)p, len, printer, arg); - break; - default: - for (clen = len; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, " %.2x", x); - } - } - - return len + CHAP_HEADERLEN; -} diff --git a/usr.sbin/pppd/chap.h b/usr.sbin/pppd/chap.h deleted file mode 100644 index be8c90d..0000000 --- a/usr.sbin/pppd/chap.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * chap.h - Challenge Handshake Authentication Protocol definitions. - * - * Copyright (c) 1993 The Australian National 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 the Australian National 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. - * - * Copyright (c) 1991 Gregory M. Christy - * 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 author. - * - * 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. - * - * $FreeBSD$ - */ - -#ifndef __CHAP_INCLUDE__ - -/* Code + ID + length */ -#define CHAP_HEADERLEN 4 - -/* - * CHAP codes. - */ - -#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */ -#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */ -#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */ -#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ - -#define CHAP_CHALLENGE 1 -#define CHAP_RESPONSE 2 -#define CHAP_SUCCESS 3 -#define CHAP_FAILURE 4 - -/* - * Challenge lengths (for challenges we send) and other limits. - */ -#define MIN_CHALLENGE_LENGTH 32 -#define MAX_CHALLENGE_LENGTH 64 -#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ - -/* - * Each interface is described by a chap structure. - */ - -typedef struct chap_state { - int unit; /* Interface unit number */ - int clientstate; /* Client state */ - int serverstate; /* Server state */ - u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */ - u_char chal_len; /* challenge length */ - u_char chal_id; /* ID of last challenge */ - u_char chal_type; /* hash algorithm for challenges */ - u_char id; /* Current id */ - char *chal_name; /* Our name to use with challenge */ - int chal_interval; /* Time until we challenge peer again */ - int timeouttime; /* Timeout time in seconds */ - int max_transmits; /* Maximum # of challenge transmissions */ - int chal_transmits; /* Number of transmissions of challenge */ - int resp_transmits; /* Number of transmissions of response */ - u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */ - u_char resp_length; /* length of response */ - u_char resp_id; /* ID for response messages */ - u_char resp_type; /* hash algorithm for responses */ - char *resp_name; /* Our name to send with response */ -} chap_state; - - -/* - * Client (peer) states. - */ -#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ -#define CHAPCS_LISTEN 3 /* Listening for a challenge */ -#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ -#define CHAPCS_OPEN 5 /* We've received Success */ - -/* - * Server (authenticator) states. - */ -#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPSS_PENDING 2 /* Auth peer when lower up */ -#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ -#define CHAPSS_OPEN 4 /* We've sent a Success msg */ -#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ -#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ - -/* - * Timeouts. - */ -#define CHAP_DEFTIMEOUT 3 /* Timeout time in seconds */ -#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ - -extern chap_state chap[]; - -void ChapAuthWithPeer(int, char *, int); -void ChapAuthPeer(int, char *, int); - -extern struct protent chap_protent; - -#define __CHAP_INCLUDE__ -#endif /* __CHAP_INCLUDE__ */ diff --git a/usr.sbin/pppd/chap_ms.c b/usr.sbin/pppd/chap_ms.c deleted file mode 100644 index 5fce6e3..0000000 --- a/usr.sbin/pppd/chap_ms.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * 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. - */ - -/* - * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 - * - * Implemented LANManager type password response to MS-CHAP challenges. - * Now pppd provides both NT style and LANMan style blocks, and the - * prefered is set by option "ms-lanman". Default is to use NT. - * The hash text (StdText) was taken from Win95 RASAPI32.DLL. - * - * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#ifdef CHAPMS - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/time.h> -#include <syslog.h> -#include <unistd.h> -#ifdef HAVE_CRYPT_H -#include <crypt.h> -#endif - -#include "pppd.h" -#include "chap.h" -#include "chap_ms.h" -#include "md4.h" - -#ifndef USE_CRYPT -#include <openssl/des.h> -#endif - -typedef struct { - u_char LANManResp[24]; - u_char NTResp[24]; - u_char UseNT; /* If 1, ignore the LANMan response field */ -} MS_ChapResponse; -/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), - in case this struct gets padded. */ - - -static void ChallengeResponse(u_char *, u_char *, u_char *); -static void DesEncrypt(u_char *, u_char *, u_char *); -static void MakeKey(u_char *, u_char *); -static u_char Get7Bits(u_char *, int); -static void ChapMS_NT(char *, int, char *, int, MS_ChapResponse *); -#ifdef MSLANMAN -static void ChapMS_LANMan(char *, int, char *, int, MS_ChapResponse *); -#endif - -#ifdef USE_CRYPT -static void Expand(u_char *, u_char *); -static void Collapse(u_char *, u_char *); -#endif - -static void -ChallengeResponse(challenge, pwHash, response) - u_char *challenge; /* IN 8 octets */ - u_char *pwHash; /* IN 16 octets */ - u_char *response; /* OUT 24 octets */ -{ - char ZPasswordHash[21]; - - BZERO(ZPasswordHash, sizeof(ZPasswordHash)); - BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE); - -#if 0 - log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); -#endif - - DesEncrypt(challenge, ZPasswordHash + 0, response + 0); - DesEncrypt(challenge, ZPasswordHash + 7, response + 8); - DesEncrypt(challenge, ZPasswordHash + 14, response + 16); - -#if 0 - log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); -#endif -} - - -#ifdef USE_CRYPT -static void -DesEncrypt(clear, key, cipher) - u_char *clear; /* IN 8 octets */ - u_char *key; /* IN 7 octets */ - u_char *cipher; /* OUT 8 octets */ -{ - u_char des_key[8]; - u_char crypt_key[66]; - u_char des_input[66]; - - MakeKey(key, des_key); - - Expand(des_key, crypt_key); - setkey(crypt_key); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X", - clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); -#endif - - Expand(clear, des_input); - encrypt(des_input, 0); - Collapse(des_input, cipher); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X", - cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); -#endif -} - -#else /* USE_CRYPT */ - -static void -DesEncrypt(clear, key, cipher) - u_char *clear; /* IN 8 octets */ - u_char *key; /* IN 7 octets */ - u_char *cipher; /* OUT 8 octets */ -{ - des_cblock des_key; - des_key_schedule key_schedule; - - MakeKey(key, des_key); - - des_set_key(&des_key, key_schedule); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X", - clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); -#endif - - des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); - -#if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X", - cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); -#endif -} - -#endif /* USE_CRYPT */ - - -static u_char Get7Bits(input, startBit) - 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; -} - -#ifdef USE_CRYPT - -/* in == 8-byte string (expanded version of the 56-bit key) - * out == 64-byte string where each byte is either 1 or 0 - * Note that the low-order "bit" is always ignored by by setkey() - */ -static void Expand(in, out) - u_char *in; - u_char *out; -{ - int j, c; - int i; - - for(i = 0; i < 64; in++){ - c = *in; - for(j = 7; j >= 0; j--) - *out++ = (c >> j) & 01; - i += 8; - } -} - -/* The inverse of Expand - */ -static void Collapse(in, out) - u_char *in; - u_char *out; -{ - int j; - int i; - unsigned int c; - - for (i = 0; i < 64; i += 8, out++) { - c = 0; - for (j = 7; j >= 0; j--, in++) - c |= *in << j; - *out = c & 0xff; - } -} -#endif - -static void MakeKey(key, des_key) - u_char *key; /* IN 56 bit DES key missing parity bits */ - u_char *des_key; /* OUT 64 bit DES key with parity bits added */ -{ - 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); - -#ifndef USE_CRYPT - des_set_odd_parity((des_cblock *)des_key); -#endif - -#if 0 - CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X", - key[0], key[1], key[2], key[3], key[4], key[5], key[6])); - CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X", - des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7])); -#endif -} - -static void -ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response) - char *rchallenge; - int rchallenge_len; - char *secret; - int secret_len; - MS_ChapResponse *response; -{ - int i; - MD4_CTX md4Context; - u_char hash[MD4_SIGNATURE_SIZE]; - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - - /* Initialize the Unicode version of the secret (== password). */ - /* This implicitly supports 8-bit ISO8859/1 characters. */ - BZERO(unicodePassword, sizeof(unicodePassword)); - for (i = 0; i < secret_len; i++) - unicodePassword[i * 2] = (u_char)secret[i]; - - MD4Init(&md4Context); - MD4Update(&md4Context, unicodePassword, secret_len * 2); /* Unicode is 2 bytes/char */ - - MD4Final(hash, &md4Context); /* Tell MD4 we're done */ - - ChallengeResponse(rchallenge, hash, response->NTResp); -} - -#ifdef MSLANMAN -static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ - -static void -ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response) - char *rchallenge; - int rchallenge_len; - char *secret; - int secret_len; - MS_ChapResponse *response; -{ - int i; - u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - - /* LANMan password is case insensitive */ - BZERO(UcasePassword, sizeof(UcasePassword)); - for (i = 0; i < secret_len; i++) - UcasePassword[i] = (u_char)toupper(secret[i]); - DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); - DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); - ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); -} -#endif - -void -ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len) - chap_state *cstate; - char *rchallenge; - int rchallenge_len; - char *secret; - int secret_len; -{ - MS_ChapResponse response; -#ifdef MSLANMAN - extern int ms_lanman; -#endif - -#if 0 - CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret)); -#endif - BZERO(&response, sizeof(response)); - - /* Calculate both always */ - ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); - -#ifdef MSLANMAN - ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); - - /* prefered method is set by option */ - response.UseNT = !ms_lanman; -#else - response.UseNT = 1; -#endif - - BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); - cstate->resp_length = MS_CHAP_RESPONSE_LEN; -} - -#endif /* CHAPMS */ diff --git a/usr.sbin/pppd/chap_ms.h b/usr.sbin/pppd/chap_ms.h deleted file mode 100644 index 6ef03c8..0000000 --- a/usr.sbin/pppd/chap_ms.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * chap.h - Challenge 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. - * - * $FreeBSD$ - */ - -#ifndef __CHAPMS_INCLUDE__ - -#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ -#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */ - -void ChapMS(chap_state *, char *, int, char *, int); - -#define __CHAPMS_INCLUDE__ -#endif /* __CHAPMS_INCLUDE__ */ diff --git a/usr.sbin/pppd/demand.c b/usr.sbin/pppd/demand.c deleted file mode 100644 index b86c81f..0000000 --- a/usr.sbin/pppd/demand.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * demand.c - Support routines for demand-dialling. - * - * Copyright (c) 1993 The Australian National 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 the Australian National 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> -#include <syslog.h> -#include <netdb.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <sys/socket.h> -#ifdef PPP_FILTER -#include <net/if.h> -#include <net/bpf.h> -#include <pcap.h> -#endif - -#include "pppd.h" -#include "fsm.h" -#include "ipcp.h" -#include "lcp.h" - -char *frame; -int framelen; -int framemax; -int escape_flag; -int flush_flag; -int fcs; - -struct packet { - int length; - struct packet *next; - unsigned char data[1]; -}; - -struct packet *pend_q; -struct packet *pend_qtail; - -static int active_packet(unsigned char *, int); - -/* - * demand_conf - configure the interface for doing dial-on-demand. - */ -void -demand_conf() -{ - int i; - struct protent *protp; - -/* framemax = lcp_allowoptions[0].mru; - if (framemax < PPP_MRU) */ - framemax = PPP_MRU; - framemax += PPP_HDRLEN + PPP_FCSLEN; - frame = malloc(framemax); - if (frame == NULL) - novm("demand frame"); - framelen = 0; - pend_q = NULL; - escape_flag = 0; - flush_flag = 0; - fcs = PPP_INITFCS; - - ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0); - ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0); - -#ifdef PPP_FILTER - set_filters(&pass_filter, &active_filter); -#endif - - /* - * Call the demand_conf procedure for each protocol that's got one. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->enabled_flag && protp->demand_conf != NULL) - if (!((*protp->demand_conf)(0))) - die(1); -} - - -/* - * demand_block - set each network protocol to block further packets. - */ -void -demand_block() -{ - int i; - struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->enabled_flag && protp->demand_conf != NULL) - sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE); - get_loop_output(); -} - -/* - * demand_discard - set each network protocol to discard packets - * with an error. - */ -void -demand_discard() -{ - struct packet *pkt, *nextpkt; - int i; - struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->enabled_flag && protp->demand_conf != NULL) - sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR); - get_loop_output(); - - /* discard all saved packets */ - for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { - nextpkt = pkt->next; - free(pkt); - } - pend_q = NULL; - framelen = 0; - flush_flag = 0; - escape_flag = 0; - fcs = PPP_INITFCS; -} - -/* - * demand_unblock - set each enabled network protocol to pass packets. - */ -void -demand_unblock() -{ - int i; - struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->enabled_flag && protp->demand_conf != NULL) - sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS); -} - -/* - * FCS lookup table as calculated by genfcstab. - */ -static u_short fcstab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -/* - * loop_chars - process characters received from the loopback. - * Calls loop_frame when a complete frame has been accumulated. - * Return value is 1 if we need to bring up the link, 0 otherwise. - */ -int -loop_chars(p, n) - unsigned char *p; - int n; -{ - int c, rv; - - rv = 0; - for (; n > 0; --n) { - c = *p++; - if (c == PPP_FLAG) { - if (!escape_flag && !flush_flag - && framelen > 2 && fcs == PPP_GOODFCS) { - framelen -= 2; - if (loop_frame(frame, framelen)) - rv = 1; - } - framelen = 0; - flush_flag = 0; - escape_flag = 0; - fcs = PPP_INITFCS; - continue; - } - if (flush_flag) - continue; - if (escape_flag) { - c ^= PPP_TRANS; - escape_flag = 0; - } else if (c == PPP_ESCAPE) { - escape_flag = 1; - continue; - } - if (framelen >= framemax) { - flush_flag = 1; - continue; - } - frame[framelen++] = c; - fcs = PPP_FCS(fcs, c); - } - return rv; -} - -/* - * loop_frame - given a frame obtained from the loopback, - * decide whether to bring up the link or not, and, if we want - * to transmit this frame later, put it on the pending queue. - * Return value is 1 if we need to bring up the link, 0 otherwise. - * We assume that the kernel driver has already applied the - * pass_filter, so we won't get packets it rejected. - * We apply the active_filter to see if we want this packet to - * bring up the link. - */ -int -loop_frame(frame, len) - unsigned char *frame; - int len; -{ - struct packet *pkt; - - /* log_packet(frame, len, "from loop: ", LOG_DEBUG); */ - if (len < PPP_HDRLEN) - return 0; - if ((PPP_PROTOCOL(frame) & 0x8000) != 0) - return 0; /* shouldn't get any of these anyway */ - if (!active_packet(frame, len)) - return 0; - - pkt = (struct packet *) malloc(sizeof(struct packet) + len); - if (pkt != NULL) { - pkt->length = len; - pkt->next = NULL; - memcpy(pkt->data, frame, len); - if (pend_q == NULL) - pend_q = pkt; - else - pend_qtail->next = pkt; - pend_qtail = pkt; - } - return 1; -} - -/* - * demand_rexmit - Resend all those frames which we got via the - * loopback, now that the real serial link is up. - */ -void -demand_rexmit(proto) - int proto; -{ - struct packet *pkt, *prev, *nextpkt; - - prev = NULL; - pkt = pend_q; - pend_q = NULL; - for (; pkt != NULL; pkt = nextpkt) { - nextpkt = pkt->next; - if (PPP_PROTOCOL(pkt->data) == proto) { - output(0, pkt->data, pkt->length); - free(pkt); - } else { - if (prev == NULL) - pend_q = pkt; - else - prev->next = pkt; - prev = pkt; - } - } - pend_qtail = prev; - if (prev != NULL) - prev->next = NULL; -} - -/* - * Scan a packet to decide whether it is an "active" packet, - * that is, whether it is worth bringing up the link for. - */ -static int -active_packet(p, len) - unsigned char *p; - int len; -{ - int proto, i; - struct protent *protp; - - if (len < PPP_HDRLEN) - return 0; - proto = PPP_PROTOCOL(p); -#ifdef PPP_FILTER - if (active_filter.bf_len != 0 - && bpf_filter(active_filter.bf_insns, frame, len, len) == 0) - return 0; -#endif - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { - if (!protp->enabled_flag) - return 0; - if (protp->active_pkt == NULL) - return 1; - return (*protp->active_pkt)(p, len); - } - } - return 0; /* not a supported protocol !!?? */ -} diff --git a/usr.sbin/pppd/eui64.c b/usr.sbin/pppd/eui64.c deleted file mode 100644 index 28335a3..0000000 --- a/usr.sbin/pppd/eui64.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - eui64.c - EUI64 routines for IPv6CP. - Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi> - - 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 Tommi Komulainen. 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: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $ -*/ - -#ifndef lint -#define RCSID "$Id: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $" -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "pppd.h" - -#ifdef RCSID -static const char rcsid[] = RCSID; -#endif - -/* - * eui64_ntoa - Make an ascii representation of an interface identifier - */ -char * -eui64_ntoa(e) - eui64_t e; -{ - static char buf[32]; - - snprintf(buf, 32, "%02x%02x:%02x%02x:%02x%02x:%02x%02x", - e.e8[0], e.e8[1], e.e8[2], e.e8[3], - e.e8[4], e.e8[5], e.e8[6], e.e8[7]); - return buf; -} diff --git a/usr.sbin/pppd/eui64.h b/usr.sbin/pppd/eui64.h deleted file mode 100644 index 4b4b505..0000000 --- a/usr.sbin/pppd/eui64.h +++ /dev/null @@ -1,98 +0,0 @@ -/* $FreeBSD$ */ -/* - eui64.h - EUI64 routines for IPv6CP. - Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi> - - 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 Tommi Komulainen. 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: eui64.h,v 1.3 1999/09/30 19:56:37 masputra Exp $ -*/ - -#ifndef __EUI64_H__ -#define __EUI64_H__ - -#if !defined(INET6) -#error "this file should only be included when INET6 is defined" -#endif /* not defined(INET6) */ - -#if defined(SOL2) -#include <netinet/in.h> - -typedef union { - uint8_t e8[8]; /* lower 64-bit IPv6 address */ - uint32_t e32[2]; /* lower 64-bit IPv6 address */ -} eui64_t; - -/* - * Declare the two below, since in.h only defines them when _KERNEL - * is declared - which shouldn't be true when dealing with user-land programs - */ -#define s6_addr8 _S6_un._S6_u8 -#define s6_addr32 _S6_un._S6_u32 - -#else /* else if not defined(SOL2) */ - -/* - * TODO: - * - * Maybe this should be done by processing struct in6_addr directly... - */ -typedef union -{ - u_int8_t e8[8]; - u_int16_t e16[4]; - u_int32_t e32[2]; -} eui64_t; - -#endif /* defined(SOL2) */ - -#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0) -#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \ - ((e).e32[1] == (o).e32[1])) -#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0; - -#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t)) - -#define eui64_magic(e) do { \ - (e).e32[0] = magic(); \ - (e).e32[1] = magic(); \ - (e).e8[0] &= ~2; \ - } while (0) -#define eui64_magic_nz(x) do { \ - eui64_magic(x); \ - } while (eui64_iszero(x)) -#define eui64_magic_ne(x, y) do { \ - eui64_magic(x); \ - } while (eui64_equals(x, y)) - -#define eui64_get(ll, cp) do { \ - eui64_copy((*cp), (ll)); \ - (cp) += sizeof(eui64_t); \ - } while (0) - -#define eui64_put(ll, cp) do { \ - eui64_copy((ll), (*cp)); \ - (cp) += sizeof(eui64_t); \ - } while (0) - -#define eui64_set32(e, l) do { \ - (e).e32[0] = 0; \ - (e).e32[1] = htonl(l); \ - } while (0) -#define eui64_setlo32(e, l) eui64_set32(e, l) - -char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */ - -#endif /* __EUI64_H__ */ - diff --git a/usr.sbin/pppd/fsm.c b/usr.sbin/pppd/fsm.c deleted file mode 100644 index 0b586b7..0000000 --- a/usr.sbin/pppd/fsm.c +++ /dev/null @@ -1,798 +0,0 @@ -/* - * fsm.c - {Link, IP} Control Protocol Finite State Machine. - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -/* - * TODO: - * Randomize fsm id on link/init. - * Deal with variable outgoing MTU. - */ - -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <syslog.h> - -#include "pppd.h" -#include "fsm.h" - -static void fsm_timeout(void *); -static void fsm_rconfreq(fsm *, int, u_char *, int); -static void fsm_rconfack(fsm *, int, u_char *, int); -static void fsm_rconfnakrej(fsm *, int, int, u_char *, int); -static void fsm_rtermreq(fsm *, int, u_char *, int); -static void fsm_rtermack(fsm *); -static void fsm_rcoderej(fsm *, u_char *, int); -static void fsm_sconfreq(fsm *, int); - -#define PROTO_NAME(f) ((f)->callbacks->proto_name) - -int peer_mru[NUM_PPP]; - - -/* - * fsm_init - Initialize fsm. - * - * Initialize fsm state. - */ -void -fsm_init(f) - fsm *f; -{ - f->state = INITIAL; - f->flags = 0; - f->id = 0; /* XXX Start with random id? */ - f->timeouttime = DEFTIMEOUT; - f->maxconfreqtransmits = DEFMAXCONFREQS; - f->maxtermtransmits = DEFMAXTERMREQS; - f->maxnakloops = DEFMAXNAKLOOPS; - f->term_reason_len = 0; -} - - -/* - * fsm_lowerup - The lower layer is up. - */ -void -fsm_lowerup(f) - fsm *f; -{ - switch( f->state ){ - case INITIAL: - f->state = CLOSED; - break; - - case STARTING: - if( f->flags & OPT_SILENT ) - f->state = STOPPED; - else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = REQSENT; - } - break; - - default: - FSMDEBUG((LOG_INFO, "%s: Up event in state %d!", - PROTO_NAME(f), f->state)); - } -} - - -/* - * fsm_lowerdown - The lower layer is down. - * - * Cancel all timeouts and inform upper layers. - */ -void -fsm_lowerdown(f) - fsm *f; -{ - switch( f->state ){ - case CLOSED: - f->state = INITIAL; - break; - - case STOPPED: - f->state = STARTING; - if( f->callbacks->starting ) - (*f->callbacks->starting)(f); - break; - - case CLOSING: - f->state = INITIAL; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case STOPPING: - case REQSENT: - case ACKRCVD: - case ACKSENT: - f->state = STARTING; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case OPENED: - if( f->callbacks->down ) - (*f->callbacks->down)(f); - f->state = STARTING; - break; - - default: - FSMDEBUG((LOG_INFO, "%s: Down event in state %d!", - PROTO_NAME(f), f->state)); - } -} - - -/* - * fsm_open - Link is allowed to come up. - */ -void -fsm_open(f) - fsm *f; -{ - switch( f->state ){ - case INITIAL: - f->state = STARTING; - if( f->callbacks->starting ) - (*f->callbacks->starting)(f); - break; - - case CLOSED: - if( f->flags & OPT_SILENT ) - f->state = STOPPED; - else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = REQSENT; - } - break; - - case CLOSING: - f->state = STOPPING; - /* FALLTHROUGH */ - case STOPPED: - case OPENED: - if( f->flags & OPT_RESTART ){ - fsm_lowerdown(f); - fsm_lowerup(f); - } - break; - } -} - - -/* - * fsm_close - Start closing connection. - * - * Cancel timeouts and either initiate close or possibly go directly to - * the CLOSED state. - */ -void -fsm_close(f, reason) - fsm *f; - char *reason; -{ - f->term_reason = reason; - f->term_reason_len = (reason == NULL? 0: strlen(reason)); - switch( f->state ){ - case STARTING: - f->state = INITIAL; - break; - case STOPPED: - f->state = CLOSED; - break; - case STOPPING: - f->state = CLOSING; - break; - - case REQSENT: - case ACKRCVD: - case ACKSENT: - case OPENED: - if( f->state != OPENED ) - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - else if( f->callbacks->down ) - (*f->callbacks->down)(f); /* Inform upper layers we're down */ - - /* Init restart counter, send Terminate-Request */ - f->retransmits = f->maxtermtransmits; - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - - f->state = CLOSING; - break; - } -} - - -/* - * fsm_timeout - Timeout expired. - */ -static void -fsm_timeout(arg) - void *arg; -{ - fsm *f = (fsm *) arg; - - switch (f->state) { - case CLOSING: - case STOPPING: - if( f->retransmits <= 0 ){ - /* - * We've waited for an ack long enough. Peer probably heard us. - */ - f->state = (f->state == CLOSING)? CLOSED: STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - } else { - /* Send Terminate-Request */ - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - } - break; - - case REQSENT: - case ACKRCVD: - case ACKSENT: - if (f->retransmits <= 0) { - syslog(LOG_WARNING, "%s: timeout sending Config-Requests", - PROTO_NAME(f)); - f->state = STOPPED; - if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) - (*f->callbacks->finished)(f); - - } else { - /* Retransmit the configure-request */ - if (f->callbacks->retransmit) - (*f->callbacks->retransmit)(f); - fsm_sconfreq(f, 1); /* Re-send Configure-Request */ - if( f->state == ACKRCVD ) - f->state = REQSENT; - } - break; - - default: - FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d!", - PROTO_NAME(f), f->state)); - } -} - - -/* - * fsm_input - Input packet. - */ -void -fsm_input(f, inpacket, l) - fsm *f; - u_char *inpacket; - int l; -{ - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (l < HEADERLEN) { - FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.", - f->protocol)); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < HEADERLEN) { - FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.", - f->protocol)); - return; - } - if (len > l) { - FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.", - f->protocol)); - return; - } - len -= HEADERLEN; /* subtract header length */ - - if( f->state == INITIAL || f->state == STARTING ){ - FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d.", - f->protocol, f->state)); - return; - } - - /* - * Action depends on code. - */ - switch (code) { - case CONFREQ: - fsm_rconfreq(f, id, inp, len); - break; - - case CONFACK: - fsm_rconfack(f, id, inp, len); - break; - - case CONFNAK: - case CONFREJ: - fsm_rconfnakrej(f, code, id, inp, len); - break; - - case TERMREQ: - fsm_rtermreq(f, id, inp, len); - break; - - case TERMACK: - fsm_rtermack(f); - break; - - case CODEREJ: - fsm_rcoderej(f, inp, len); - break; - - default: - if( !f->callbacks->extcode - || !(*f->callbacks->extcode)(f, code, id, inp, len) ) - fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); - break; - } -} - - -/* - * fsm_rconfreq - Receive Configure-Request. - */ -static void -fsm_rconfreq(f, id, inp, len) - fsm *f; - u_char id; - u_char *inp; - int len; -{ - int code, reject_if_disagree; - - FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d.", PROTO_NAME(f), id)); - switch( f->state ){ - case CLOSED: - /* Go away, we're closed */ - fsm_sdata(f, TERMACK, id, NULL, 0); - return; - case CLOSING: - case STOPPING: - return; - - case OPENED: - /* Go down and restart negotiation */ - if( f->callbacks->down ) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - break; - - case STOPPED: - /* Negotiation started by our peer */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = REQSENT; - break; - } - - /* - * Pass the requested configuration options - * to protocol-specific code for checking. - */ - if (f->callbacks->reqci){ /* Check CI */ - reject_if_disagree = (f->nakloops >= f->maxnakloops); - code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); - } else if (len) - code = CONFREJ; /* Reject all CI */ - else - code = CONFACK; - - /* send the Ack, Nak or Rej to the peer */ - fsm_sdata(f, code, id, inp, len); - - if (code == CONFACK) { - if (f->state == ACKRCVD) { - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = OPENED; - if (f->callbacks->up) - (*f->callbacks->up)(f); /* Inform upper layers */ - } else - f->state = ACKSENT; - f->nakloops = 0; - - } else { - /* we sent CONFACK or CONFREJ */ - if (f->state != ACKRCVD) - f->state = REQSENT; - if( code == CONFNAK ) - ++f->nakloops; - } -} - - -/* - * fsm_rconfack - Receive Configure-Ack. - */ -static void -fsm_rconfack(f, id, inp, len) - fsm *f; - int id; - u_char *inp; - int len; -{ - FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d.", - PROTO_NAME(f), id)); - - if (id != f->reqid || f->seen_ack) /* Expected id? */ - return; /* Nope, toss... */ - if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): - (len == 0)) ){ - /* Ack is bad - ignore it */ - log_packet(inp, len, "Received bad configure-ack: ", LOG_ERR); - FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)", - PROTO_NAME(f), len)); - return; - } - f->seen_ack = 1; - - switch (f->state) { - case CLOSED: - case STOPPED: - fsm_sdata(f, TERMACK, id, NULL, 0); - break; - - case REQSENT: - f->state = ACKRCVD; - f->retransmits = f->maxconfreqtransmits; - break; - - case ACKRCVD: - /* Huh? an extra valid Ack? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = REQSENT; - break; - - case ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = OPENED; - f->retransmits = f->maxconfreqtransmits; - if (f->callbacks->up) - (*f->callbacks->up)(f); /* Inform upper layers */ - break; - - case OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = REQSENT; - break; - } -} - - -/* - * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. - */ -static void -fsm_rconfnakrej(f, code, id, inp, len) - fsm *f; - int code, id; - u_char *inp; - int len; -{ - int (*proc)(fsm *, u_char *, int); - int ret; - - FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d.", - PROTO_NAME(f), id)); - - if (id != f->reqid || f->seen_ack) /* Expected id? */ - return; /* Nope, toss... */ - proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; - if (!proc || !(ret = proc(f, inp, len))) { - /* Nak/reject is bad - ignore it */ - log_packet(inp, len, "Received bad configure-nak/rej: ", LOG_ERR); - FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)", - PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); - return; - } - f->seen_ack = 1; - - switch (f->state) { - case CLOSED: - case STOPPED: - fsm_sdata(f, TERMACK, id, NULL, 0); - break; - - case REQSENT: - case ACKSENT: - /* They didn't agree to what we wanted - try another request */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - if (ret < 0) - f->state = STOPPED; /* kludge for stopping CCP */ - else - fsm_sconfreq(f, 0); /* Send Configure-Request */ - break; - - case ACKRCVD: - /* Got a Nak/reject when we had already had an Ack?? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = REQSENT; - break; - - case OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = REQSENT; - break; - } -} - - -/* - * fsm_rtermreq - Receive Terminate-Req. - */ -static void -fsm_rtermreq(f, id, p, len) - fsm *f; - int id; - u_char *p; - int len; -{ - char str[80]; - - FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d.", - PROTO_NAME(f), id)); - - switch (f->state) { - case ACKRCVD: - case ACKSENT: - f->state = REQSENT; /* Start over but keep trying */ - break; - - case OPENED: - if (len > 0) { - fmtmsg(str, sizeof(str), "%0.*v", len, p); - syslog(LOG_INFO, "%s terminated by peer (%s)", PROTO_NAME(f), str); - } else - syslog(LOG_INFO, "%s terminated by peer", PROTO_NAME(f)); - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - f->retransmits = 0; - f->state = STOPPING; - TIMEOUT(fsm_timeout, f, f->timeouttime); - break; - } - - fsm_sdata(f, TERMACK, id, NULL, 0); -} - - -/* - * fsm_rtermack - Receive Terminate-Ack. - */ -static void -fsm_rtermack(f) - fsm *f; -{ - FSMDEBUG((LOG_INFO, "fsm_rtermack(%s).", PROTO_NAME(f))); - - switch (f->state) { - case CLOSING: - UNTIMEOUT(fsm_timeout, f); - f->state = CLOSED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - case STOPPING: - UNTIMEOUT(fsm_timeout, f); - f->state = STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case ACKRCVD: - f->state = REQSENT; - break; - - case OPENED: - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); - break; - } -} - - -/* - * fsm_rcoderej - Receive a Code-Reject. - */ -static void -fsm_rcoderej(f, inp, len) - fsm *f; - u_char *inp; - int len; -{ - u_char code, id; - - FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s).", PROTO_NAME(f))); - - if (len < HEADERLEN) { - FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - syslog(LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d", - PROTO_NAME(f), code, id); - - if( f->state == ACKRCVD ) - f->state = REQSENT; -} - - -/* - * fsm_protreject - Peer doesn't speak this protocol. - * - * Treat this as a catastrophic error (RXJ-). - */ -void -fsm_protreject(f) - fsm *f; -{ - switch( f->state ){ - case CLOSING: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* FALLTHROUGH */ - case CLOSED: - f->state = CLOSED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case STOPPING: - case REQSENT: - case ACKRCVD: - case ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* FALLTHROUGH */ - case STOPPED: - f->state = STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case OPENED: - if( f->callbacks->down ) - (*f->callbacks->down)(f); - - /* Init restart counter, send Terminate-Request */ - f->retransmits = f->maxtermtransmits; - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - - f->state = STOPPING; - break; - - default: - FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d!", - PROTO_NAME(f), f->state)); - } -} - - -/* - * fsm_sconfreq - Send a Configure-Request. - */ -static void -fsm_sconfreq(f, retransmit) - fsm *f; - int retransmit; -{ - u_char *outp; - int cilen; - - if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){ - /* Not currently negotiating - reset options */ - if( f->callbacks->resetci ) - (*f->callbacks->resetci)(f); - f->nakloops = 0; - } - - if( !retransmit ){ - /* New request - reset retransmission counter, use new ID */ - f->retransmits = f->maxconfreqtransmits; - f->reqid = ++f->id; - } - - f->seen_ack = 0; - - /* - * Make up the request packet - */ - outp = outpacket_buf + PPP_HDRLEN + HEADERLEN; - if( f->callbacks->cilen && f->callbacks->addci ){ - cilen = (*f->callbacks->cilen)(f); - if( cilen > peer_mru[f->unit] - HEADERLEN ) - cilen = peer_mru[f->unit] - HEADERLEN; - if (f->callbacks->addci) - (*f->callbacks->addci)(f, outp, &cilen); - } else - cilen = 0; - - /* send the request to our peer */ - fsm_sdata(f, CONFREQ, f->reqid, outp, cilen); - - /* start the retransmit timer */ - --f->retransmits; - TIMEOUT(fsm_timeout, f, f->timeouttime); - - FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d", - PROTO_NAME(f), f->reqid)); -} - - -/* - * fsm_sdata - Send some data. - * - * Used for all packets sent to our peer by this module. - */ -void -fsm_sdata(f, code, id, data, datalen) - fsm *f; - u_char code, id; - u_char *data; - int datalen; -{ - u_char *outp; - int outlen; - - /* Adjust length to be smaller than MTU */ - outp = outpacket_buf; - if (datalen > peer_mru[f->unit] - HEADERLEN) - datalen = peer_mru[f->unit] - HEADERLEN; - if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) - BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); - outlen = datalen + HEADERLEN; - MAKEHEADER(outp, f->protocol); - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - output(f->unit, outpacket_buf, outlen + PPP_HDRLEN); - - FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d, id %d.", - PROTO_NAME(f), code, id)); -} diff --git a/usr.sbin/pppd/fsm.h b/usr.sbin/pppd/fsm.h deleted file mode 100644 index 053c833..0000000 --- a/usr.sbin/pppd/fsm.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * Packet header = Code, id, length. - */ -#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) - - -/* - * CP (LCP, IPCP, etc.) codes. - */ -#define CONFREQ 1 /* Configuration Request */ -#define CONFACK 2 /* Configuration Ack */ -#define CONFNAK 3 /* Configuration Nak */ -#define CONFREJ 4 /* Configuration Reject */ -#define TERMREQ 5 /* Termination Request */ -#define TERMACK 6 /* Termination Ack */ -#define CODEREJ 7 /* Code Reject */ - - -/* - * Each FSM is described by an fsm structure and fsm callbacks. - */ -typedef struct fsm { - int unit; /* Interface unit number */ - int protocol; /* Data Link Layer Protocol field value */ - int state; /* State */ - int flags; /* Contains option bits */ - u_char id; /* Current id */ - u_char reqid; /* Current request id */ - u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */ - int timeouttime; /* Timeout time in milliseconds */ - int maxconfreqtransmits; /* Maximum Configure-Request transmissions */ - int retransmits; /* Number of retransmissions left */ - int maxtermtransmits; /* Maximum Terminate-Request transmissions */ - int nakloops; /* Number of nak loops since last ack */ - int maxnakloops; /* Maximum number of nak loops tolerated */ - struct fsm_callbacks *callbacks; /* Callback routines */ - char *term_reason; /* Reason for closing protocol */ - int term_reason_len; /* Length of term_reason */ -} fsm; - - -typedef struct fsm_callbacks { - void (*resetci) /* Reset our Configuration Information */ - (fsm *); - int (*cilen) /* Length of our Configuration Information */ - (fsm *); - void (*addci) /* Add our Configuration Information */ - (fsm *, u_char *, int *); - int (*ackci) /* ACK our Configuration Information */ - (fsm *, u_char *, int); - int (*nakci) /* NAK our Configuration Information */ - (fsm *, u_char *, int); - int (*rejci) /* Reject our Configuration Information */ - (fsm *, u_char *, int); - int (*reqci) /* Request peer's Configuration Information */ - (fsm *, u_char *, int *, int); - void (*up) /* Called when fsm reaches OPENED state */ - (fsm *); - void (*down) /* Called when fsm leaves OPENED state */ - (fsm *); - void (*starting) /* Called when we want the lower layer */ - (fsm *); - void (*finished) /* Called when we don't want the lower layer */ - (fsm *); - void (*protreject) /* Called when Protocol-Reject received */ - (int); - void (*retransmit) /* Retransmission is necessary */ - (fsm *); - int (*extcode) /* Called when unknown code received */ - (fsm *, int, int, u_char *, int); - char *proto_name; /* String name for protocol (for messages) */ -} fsm_callbacks; - - -/* - * Link states. - */ -#define INITIAL 0 /* Down, hasn't been opened */ -#define STARTING 1 /* Down, been opened */ -#define CLOSED 2 /* Up, hasn't been opened */ -#define STOPPED 3 /* Open, waiting for down event */ -#define CLOSING 4 /* Terminating the connection, not open */ -#define STOPPING 5 /* Terminating, but open */ -#define REQSENT 6 /* We've sent a Config Request */ -#define ACKRCVD 7 /* We've received a Config Ack */ -#define ACKSENT 8 /* We've sent a Config Ack */ -#define OPENED 9 /* Connection available */ - - -/* - * Flags - indicate options controlling FSM operation - */ -#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ -#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ -#define OPT_SILENT 4 /* Wait for peer to speak first */ - - -/* - * Timeouts. - */ -#define DEFTIMEOUT 3 /* Timeout time in seconds */ -#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ -#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ -#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ - - -/* - * Prototypes - */ -void fsm_init(fsm *); -void fsm_lowerup(fsm *); -void fsm_lowerdown(fsm *); -void fsm_open(fsm *); -void fsm_close(fsm *, char *); -void fsm_input(fsm *, u_char *, int); -void fsm_protreject(fsm *); -void fsm_sdata(fsm *, int, int, u_char *, int); - - -/* - * Variables - */ -extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */ diff --git a/usr.sbin/pppd/ipcp.c b/usr.sbin/pppd/ipcp.c deleted file mode 100644 index 3369757..0000000 --- a/usr.sbin/pppd/ipcp.c +++ /dev/null @@ -1,1531 +0,0 @@ -/* - * ipcp.c - PPP IP Control Protocol. - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -/* - * TODO: - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <netdb.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> - -#include "pppd.h" -#include "fsm.h" -#include "ipcp.h" -#include "pathnames.h" - -/* global vars */ -ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ -ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ - -/* local vars */ -static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ -static int default_route_set[NUM_PPP]; /* Have set up a default route */ -static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipcp_resetci(fsm *); /* Reset our CI */ -static int ipcp_cilen(fsm *); /* Return length of our CI */ -static void ipcp_addci(fsm *, u_char *, int *); /* Add our CI */ -static int ipcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */ -static int ipcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */ -static int ipcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */ -static int ipcp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */ -static void ipcp_up(fsm *); /* We're UP */ -static void ipcp_down(fsm *); /* We're DOWN */ -static void ipcp_script(fsm *, char *); /* Run an up/down script */ -static void ipcp_finished(fsm *); /* Don't need lower layer */ - -fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ - -static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ - ipcp_resetci, /* Reset our Configuration Information */ - ipcp_cilen, /* Length of our Configuration Information */ - ipcp_addci, /* Add our Configuration Information */ - ipcp_ackci, /* ACK our Configuration Information */ - ipcp_nakci, /* NAK our Configuration Information */ - ipcp_rejci, /* Reject our Configuration Information */ - ipcp_reqci, /* Request peer's Configuration Information */ - ipcp_up, /* Called when fsm reaches OPENED state */ - ipcp_down, /* Called when fsm leaves OPENED state */ - NULL, /* Called when we want the lower layer up */ - ipcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPCP" /* String name of protocol */ -}; - -/* - * Protocol entry points from main code. - */ -static void ipcp_init(int); -static void ipcp_open(int); -static void ipcp_close(int, char *); -static void ipcp_lowerup(int); -static void ipcp_lowerdown(int); -static void ipcp_input(int, u_char *, int); -static void ipcp_protrej(int); -static int ipcp_printpkt(u_char *, int, - void (*) (void *, char *, ...), void *); -static void ip_check_options(void); -static int ip_demand_conf(int); -static int ip_active_pkt(u_char *, int); - -struct protent ipcp_protent = { - PPP_IPCP, - ipcp_init, - ipcp_input, - ipcp_protrej, - ipcp_lowerup, - ipcp_lowerdown, - ipcp_open, - ipcp_close, - ipcp_printpkt, - NULL, - 1, - "IPCP", - ip_check_options, - ip_demand_conf, - ip_active_pkt -}; - -static void ipcp_clear_addrs(int); - -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ -#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ -#define CILEN_ADDR 6 /* new-style single address option */ -#define CILEN_ADDRS 10 /* old-style dual address option */ - - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - - -/* - * Make a string representation of a network IP address. - */ -char * -ip_ntoa(ipaddr) -u_int32_t ipaddr; -{ - static char b[64]; - - ipaddr = ntohl(ipaddr); - - sprintf(b, "%d.%d.%d.%d", - (u_char)(ipaddr >> 24), - (u_char)(ipaddr >> 16), - (u_char)(ipaddr >> 8), - (u_char)(ipaddr)); - return b; -} - - -/* - * ipcp_init - Initialize IPCP. - */ -static void -ipcp_init(unit) - int unit; -{ - fsm *f = &ipcp_fsm[unit]; - ipcp_options *wo = &ipcp_wantoptions[unit]; - ipcp_options *ao = &ipcp_allowoptions[unit]; - - f->unit = unit; - f->protocol = PPP_IPCP; - f->callbacks = &ipcp_callbacks; - fsm_init(&ipcp_fsm[unit]); - - memset(wo, 0, sizeof(*wo)); - memset(ao, 0, sizeof(*ao)); - - wo->neg_addr = 1; - wo->neg_vj = 1; - wo->vj_protocol = IPCP_VJ_COMP; - wo->maxslotindex = MAX_STATES - 1; /* really max index */ - wo->cflag = 1; - - /* max slots and slot-id compression are currently hardwired in */ - /* ppp_if.c to 16 and 1, this needs to be changed (among other */ - /* things) gmc */ - - ao->neg_addr = 1; - ao->neg_vj = 1; - ao->maxslotindex = MAX_STATES - 1; - ao->cflag = 1; - - /* - * XXX These control whether the user may use the proxyarp - * and defaultroute options. - */ - ao->proxy_arp = 1; - ao->default_route = 1; -} - - -/* - * ipcp_open - IPCP is allowed to come up. - */ -static void -ipcp_open(unit) - int unit; -{ - fsm_open(&ipcp_fsm[unit]); -} - - -/* - * ipcp_close - Take IPCP down. - */ -static void -ipcp_close(unit, reason) - int unit; - char *reason; -{ - fsm_close(&ipcp_fsm[unit], reason); -} - - -/* - * ipcp_lowerup - The lower layer is up. - */ -static void -ipcp_lowerup(unit) - int unit; -{ - fsm_lowerup(&ipcp_fsm[unit]); -} - - -/* - * ipcp_lowerdown - The lower layer is down. - */ -static void -ipcp_lowerdown(unit) - int unit; -{ - fsm_lowerdown(&ipcp_fsm[unit]); -} - - -/* - * ipcp_input - Input IPCP packet. - */ -static void -ipcp_input(unit, p, len) - int unit; - u_char *p; - int len; -{ - fsm_input(&ipcp_fsm[unit], p, len); -} - - -/* - * ipcp_protrej - A Protocol-Reject was received for IPCP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void -ipcp_protrej(unit) - int unit; -{ - fsm_lowerdown(&ipcp_fsm[unit]); -} - - -/* - * ipcp_resetci - Reset our CI. - */ -static void -ipcp_resetci(f) - fsm *f; -{ - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - - wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; - if (wo->ouraddr == 0) - wo->accept_local = 1; - if (wo->hisaddr == 0) - wo->accept_remote = 1; - ipcp_gotoptions[f->unit] = *wo; - cis_received[f->unit] = 0; -} - - -/* - * ipcp_cilen - Return length of our CI. - */ -static int -ipcp_cilen(f) - fsm *f; -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - ipcp_options *ho = &ipcp_hisoptions[f->unit]; - -#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) -#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) - - /* - * First see if we want to change our options to the old - * forms because we have received old forms from the peer. - */ - if (wo->neg_addr && !go->neg_addr && !go->old_addrs) { - /* use the old style of address negotiation */ - go->neg_addr = 1; - go->old_addrs = 1; - } - if (wo->neg_vj && !go->neg_vj && !go->old_vj) { - /* try an older style of VJ negotiation */ - if (cis_received[f->unit] == 0) { - /* keep trying the new style until we see some CI from the peer */ - go->neg_vj = 1; - } else { - /* use the old style only if the peer did */ - if (ho->neg_vj && ho->old_vj) { - go->neg_vj = 1; - go->old_vj = 1; - go->vj_protocol = ho->vj_protocol; - } - } - } - - return (LENCIADDR(go->neg_addr, go->old_addrs) + - LENCIVJ(go->neg_vj, go->old_vj)); -} - - -/* - * ipcp_addci - Add our desired CIs to a packet. - */ -static void -ipcp_addci(f, ucp, lenp) - fsm *f; - u_char *ucp; - int *lenp; -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - int len = *lenp; - -#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if (len >= vjlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(vjlen, ucp); \ - PUTSHORT(val, ucp); \ - if (!old) { \ - PUTCHAR(maxslotindex, ucp); \ - PUTCHAR(cflag, ucp); \ - } \ - len -= vjlen; \ - } else \ - neg = 0; \ - } - -#define ADDCIADDR(opt, neg, old, val1, val2) \ - if (neg) { \ - int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ - if (len >= addrlen) { \ - u_int32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(addrlen, ucp); \ - l = ntohl(val1); \ - PUTLONG(l, ucp); \ - if (old) { \ - l = ntohl(val2); \ - PUTLONG(l, ucp); \ - } \ - len -= addrlen; \ - } else \ - neg = 0; \ - } - - ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, - go->old_addrs, go->ouraddr, go->hisaddr); - - ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); - - *lenp -= len; -} - - -/* - * ipcp_ackci - Ack our CIs. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int -ipcp_ackci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - u_short cilen, citype, cishort; - u_int32_t cilong; - u_char cimaxslotindex, cicflag; - - /* - * CIs must be in exactly the same order that we sent... - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - -#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if ((len -= vjlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != vjlen || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslotindex) \ - goto bad; \ - GETCHAR(cicflag, p); \ - if (cicflag != cflag) \ - goto bad; \ - } \ - } - -#define ACKCIADDR(opt, neg, old, val1, val2) \ - if (neg) { \ - int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ - u_int32_t l; \ - if ((len -= addrlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != addrlen || \ - citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = htonl(l); \ - if (val1 != cilong) \ - goto bad; \ - if (old) { \ - GETLONG(l, p); \ - cilong = htonl(l); \ - if (val2 != cilong) \ - goto bad; \ - } \ - } - - ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr, - go->old_addrs, go->ouraddr, go->hisaddr); - - ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); - -bad: - IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!")); - return (0); -} - -/* - * ipcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPCP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int -ipcp_nakci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - u_char cimaxslotindex, cicflag; - u_char citype, cilen, *next; - u_short cishort; - u_int32_t ciaddr1, ciaddr2, l; - ipcp_options no; /* options we've seen Naks for */ - ipcp_options try; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIADDR(opt, neg, old, code) \ - if (go->neg && \ - len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - ciaddr1 = htonl(l); \ - if (old) { \ - GETLONG(l, p); \ - ciaddr2 = htonl(l); \ - no.old_addrs = 1; \ - } else \ - ciaddr2 = 0; \ - no.neg = 1; \ - code \ - } - -#define NAKCIVJ(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } - - /* - * Accept the peer's idea of {our,his} address, if different - * from our idea, only if the accept_{local,remote} flag is set. - */ - NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, - if (go->accept_local && ciaddr1) { /* Do we know our address? */ - try.ouraddr = ciaddr1; - IPCPDEBUG((LOG_INFO, "local IP address %s", - ip_ntoa(ciaddr1))); - } - if (go->accept_remote && ciaddr2) { /* Does he know his? */ - try.hisaddr = ciaddr2; - IPCPDEBUG((LOG_INFO, "remote IP address %s", - ip_ntoa(ciaddr2))); - } - ); - - /* - * Accept the peer's value of maxslotindex provided that it - * is less than what we asked for. Turn off slot-ID compression - * if the peer wants. Send old-style compress-type option if - * the peer wants. - */ - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - if (cilen == CILEN_VJ) { - GETCHAR(cimaxslotindex, p); - GETCHAR(cicflag, p); - if (cishort == IPCP_VJ_COMP) { - try.old_vj = 0; - if (cimaxslotindex < go->maxslotindex) - try.maxslotindex = cimaxslotindex; - if (!cicflag) - try.cflag = 0; - } else { - try.neg_vj = 0; - } - } else { - if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { - try.old_vj = 1; - try.vj_protocol = cishort; - } else { - try.neg_vj = 0; - } - } - ); - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If they want to negotiate about IP addresses, we comply. - * If they want us to ask for compression, we refuse. - */ - while (len > CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if( (len -= cilen) < 0 ) - goto bad; - next = p + cilen - 2; - - switch (citype) { - case CI_COMPRESSTYPE: - if (go->neg_vj || no.neg_vj || - (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) - goto bad; - no.neg_vj = 1; - break; - case CI_ADDRS: - if ((go->neg_addr && go->old_addrs) || no.old_addrs - || cilen != CILEN_ADDRS) - goto bad; - try.neg_addr = 1; - try.old_addrs = 1; - GETLONG(l, p); - ciaddr1 = htonl(l); - if (ciaddr1 && go->accept_local) - try.ouraddr = ciaddr1; - GETLONG(l, p); - ciaddr2 = htonl(l); - if (ciaddr2 && go->accept_remote) - try.hisaddr = ciaddr2; - no.old_addrs = 1; - break; - case CI_ADDR: - if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) - goto bad; - try.old_addrs = 0; - GETLONG(l, p); - ciaddr1 = htonl(l); - if (ciaddr1 && go->accept_local) - try.ouraddr = ciaddr1; - if (try.ouraddr != 0) - try.neg_addr = 1; - no.neg_addr = 1; - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) - goto bad; - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != OPENED) - *go = try; - - return 1; - -bad: - IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!")); - return 0; -} - - -/* - * ipcp_rejci - Reject some of our CIs. - */ -static int -ipcp_rejci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ipcp_options *go = &ipcp_gotoptions[f->unit]; - u_char cimaxslotindex, ciflag, cilen; - u_short cishort; - u_int32_t cilong; - ipcp_options try; /* options to request next time */ - - try = *go; - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIADDR(opt, neg, old, val1, val2) \ - if (go->neg && \ - len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ - p[1] == cilen && \ - p[0] == opt) { \ - u_int32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val1) \ - goto bad; \ - if (old) { \ - GETLONG(l, p); \ - cilong = htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val2) \ - goto bad; \ - } \ - try.neg = 0; \ - } - -#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ - if (go->neg && \ - p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ - len >= p[1] && \ - p[0] == opt) { \ - len -= p[1]; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslot) \ - goto bad; \ - GETCHAR(ciflag, p); \ - if (ciflag != cflag) \ - goto bad; \ - } \ - try.neg = 0; \ - } - - REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, - go->old_addrs, go->ouraddr, go->hisaddr); - - REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != OPENED) - *go = try; - return 1; - -bad: - IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!")); - return 0; -} - - -/* - * ipcp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - */ -static int -ipcp_reqci(f, inp, len, reject_if_disagree) - fsm *f; - u_char *inp; /* Requested CIs */ - int *len; /* Length of requested CIs */ - int reject_if_disagree; -{ - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - ipcp_options *ho = &ipcp_hisoptions[f->unit]; - ipcp_options *ao = &ipcp_allowoptions[f->unit]; - ipcp_options *go = &ipcp_gotoptions[f->unit]; - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ - u_short cishort; /* Parsed short value */ - u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ - u_char maxslotindex, cflag; - int d; - - cis_received[f->unit] = 1; - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_ADDRS: - IPCPDEBUG((LOG_INFO, "ipcp: received ADDRS ")); - if (!ao->neg_addr || - cilen != CILEN_ADDRS) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = htonl(tl); - IPCPDEBUG((LOG_INFO, "(%s:", ip_ntoa(ciaddr1))); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u_int32_t), p); - tl = ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * If neither we nor he knows his address, reject the option. - */ - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - /* - * If he doesn't know our address, or if we both have our address - * but disagree about it, then NAK it with our idea. - */ - GETLONG(tl, p); /* Parse desination address (ours) */ - ciaddr2 = htonl(tl); - IPCPDEBUG((LOG_INFO, "%s)", ip_ntoa(ciaddr2))); - if (ciaddr2 != wo->ouraddr) { - if (ciaddr2 == 0 || !wo->accept_local) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u_int32_t), p); - tl = ntohl(wo->ouraddr); - PUTLONG(tl, p); - } - } else { - go->ouraddr = ciaddr2; /* accept peer's idea */ - } - } - - ho->neg_addr = 1; - ho->old_addrs = 1; - ho->hisaddr = ciaddr1; - ho->ouraddr = ciaddr2; - break; - - case CI_ADDR: - IPCPDEBUG((LOG_INFO, "ipcp: received ADDR ")); - - if (!ao->neg_addr || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = htonl(tl); - IPCPDEBUG((LOG_INFO, "(%s)", ip_ntoa(ciaddr1))); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u_int32_t), p); - tl = ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * Don't ACK an address of 0.0.0.0 - reject it instead. - */ - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - ho->neg_addr = 1; - ho->hisaddr = ciaddr1; - break; - - case CI_MS_DNS1: - case CI_MS_DNS2: - /* Microsoft primary or secondary DNS request */ - d = citype == CI_MS_DNS2; - IPCPDEBUG((LOG_INFO, "ipcp: received DNS%d Request ", d+1)); - - /* If we do not have a DNS address then we cannot send it */ - if (ao->dnsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (htonl(tl) != ao->dnsaddr[d]) { - DECPTR(sizeof(u_int32_t), p); - tl = ntohl(ao->dnsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - break; - - case CI_MS_WINS1: - case CI_MS_WINS2: - /* Microsoft primary or secondary WINS request */ - d = citype == CI_MS_WINS2; - IPCPDEBUG((LOG_INFO, "ipcp: received WINS%d Request ", d+1)); - - /* If we do not have a DNS address then we cannot send it */ - if (ao->winsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (htonl(tl) != ao->winsaddr[d]) { - DECPTR(sizeof(u_int32_t), p); - tl = ntohl(ao->winsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - break; - - case CI_COMPRESSTYPE: - IPCPDEBUG((LOG_INFO, "ipcp: received COMPRESSTYPE ")); - if (!ao->neg_vj || - (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - IPCPDEBUG((LOG_INFO, "(%d)", cishort)); - - if (!(cishort == IPCP_VJ_COMP || - (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { - orc = CONFREJ; - break; - } - - ho->neg_vj = 1; - ho->vj_protocol = cishort; - if (cilen == CILEN_VJ) { - GETCHAR(maxslotindex, p); - if (maxslotindex > ao->maxslotindex) { - orc = CONFNAK; - if (!reject_if_disagree){ - DECPTR(1, p); - PUTCHAR(ao->maxslotindex, p); - } - } - GETCHAR(cflag, p); - if (cflag && !ao->cflag) { - orc = CONFNAK; - if (!reject_if_disagree){ - DECPTR(1, p); - PUTCHAR(wo->cflag, p); - } - } - ho->maxslotindex = maxslotindex; - ho->cflag = cflag; - } else { - ho->old_vj = 1; - ho->maxslotindex = MAX_STATES - 1; - ho->cflag = 1; - } - break; - - default: - orc = CONFREJ; - break; - } - -endswitch: - IPCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc))); - - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ - orc = CONFREJ; /* Get tough if so */ - else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) - BCOPY(cip, ucp, cilen); /* Move it */ - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their address, and they didn't send their address, then we - * send a NAK with a CI_ADDR option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - if (rc != CONFREJ && !ho->neg_addr && - wo->req_addr && !reject_if_disagree) { - if (rc == CONFACK) { - rc = CONFNAK; - ucp = inp; /* reset pointer */ - wo->req_addr = 0; /* don't ask again */ - } - PUTCHAR(CI_ADDR, ucp); - PUTCHAR(CILEN_ADDR, ucp); - tl = ntohl(wo->hisaddr); - PUTLONG(tl, ucp); - } - - *len = ucp - inp; /* Compute output length */ - IPCPDEBUG((LOG_INFO, "ipcp: returning Configure-%s", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -/* - * ip_check_options - check that any IP-related options are OK, - * and assign appropriate defaults. - */ -static void -ip_check_options() -{ - struct hostent *hp; - u_int32_t local; - ipcp_options *wo = &ipcp_wantoptions[0]; - - /* - * Default our local IP address based on our hostname. - * If local IP address already given, don't bother. - */ - if (wo->ouraddr == 0 && !disable_defaultip) { - /* - * Look up our hostname (possibly with domain name appended) - * and take the first IP address as our local IP address. - * If there isn't an IP address for our hostname, too bad. - */ - wo->accept_local = 1; /* don't insist on this default value */ - if ((hp = gethostbyname(hostname)) != NULL) { - local = *(u_int32_t *)hp->h_addr; - if (local != 0 && !bad_ip_adrs(local)) - wo->ouraddr = local; - } - } - - if (demand && wo->hisaddr == 0) { - option_error("remote IP address required for demand-dialling\n"); - exit(1); - } -#if 0 - if (demand && wo->accept_remote) { - option_error("ipcp-accept-remote is incompatible with demand\n"); - exit(1); - } -#endif -} - - -/* - * ip_demand_conf - configure the interface as though - * IPCP were up, for use with dial-on-demand. - */ -static int -ip_demand_conf(u) - int u; -{ - ipcp_options *wo = &ipcp_wantoptions[u]; - - if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr))) - return 0; - if (!sifup(u)) - return 0; - if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE)) - return 0; - if (wo->default_route) - if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr)) - default_route_set[u] = 1; - if (wo->proxy_arp) - if (sifproxyarp(u, wo->hisaddr)) - proxy_arp_set[u] = 1; - - syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(wo->ouraddr)); - syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(wo->hisaddr)); - - return 1; -} - - -/* - * ipcp_up - IPCP has come UP. - * - * Configure the IP network interface appropriately and bring it up. - */ -static void -ipcp_up(f) - fsm *f; -{ - u_int32_t mask; - ipcp_options *ho = &ipcp_hisoptions[f->unit]; - ipcp_options *go = &ipcp_gotoptions[f->unit]; - ipcp_options *wo = &ipcp_wantoptions[f->unit]; - - np_up(f->unit, PPP_IP); - IPCPDEBUG((LOG_INFO, "ipcp: up")); - - /* - * We must have a non-zero IP address for both ends of the link. - */ - if (!ho->neg_addr) - ho->hisaddr = wo->hisaddr; - - if (ho->hisaddr == 0) { - syslog(LOG_ERR, "Could not determine remote IP address"); - ipcp_close(f->unit, "Could not determine remote IP address"); - return; - } - if (go->ouraddr == 0) { - syslog(LOG_ERR, "Could not determine local IP address"); - ipcp_close(f->unit, "Could not determine local IP address"); - return; - } - script_setenv("IPLOCAL", ip_ntoa(go->ouraddr)); - script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr)); - - /* - * Check that the peer is allowed to use the IP address it wants. - */ - if (!auth_ip_addr(f->unit, ho->hisaddr)) { - syslog(LOG_ERR, "Peer is not authorized to use remote address %s", - ip_ntoa(ho->hisaddr)); - ipcp_close(f->unit, "Unauthorized remote IP address"); - return; - } - - /* set tcp compression */ - sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); - - /* - * If we are doing dial-on-demand, the interface is already - * configured, so we put out any saved-up packets, then set the - * interface to pass IP packets. - */ - if (demand) { - if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { - if (go->ouraddr != wo->ouraddr) - syslog(LOG_WARNING, "Local IP address changed to %s", - ip_ntoa(go->ouraddr)); - if (ho->hisaddr != wo->hisaddr) - syslog(LOG_WARNING, "Remote IP address changed to %s", - ip_ntoa(ho->hisaddr)); - ipcp_clear_addrs(f->unit); - - /* Set the interface to the new addresses */ - mask = GetMask(go->ouraddr); - if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { - IPCPDEBUG((LOG_WARNING, "sifaddr failed")); - ipcp_close(f->unit, "Interface configuration failed"); - return; - } - - /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) - default_route_set[f->unit] = 1; - - /* Make a proxy ARP entry if requested. */ - if (ipcp_wantoptions[f->unit].proxy_arp) - if (sifproxyarp(f->unit, ho->hisaddr)) - proxy_arp_set[f->unit] = 1; - - } - demand_rexmit(PPP_IP); - sifnpmode(f->unit, PPP_IP, NPMODE_PASS); - - } else { - /* - * Set IP addresses and (if specified) netmask. - */ - mask = GetMask(go->ouraddr); - -#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { - IPCPDEBUG((LOG_WARNING, "sifaddr failed")); - ipcp_close(f->unit, "Interface configuration failed"); - return; - } -#endif - - /* bring the interface up for IP */ - if (!sifup(f->unit)) { - IPCPDEBUG((LOG_WARNING, "sifup failed")); - ipcp_close(f->unit, "Interface configuration failed"); - return; - } - -#if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { - IPCPDEBUG((LOG_WARNING, "sifaddr failed")); - ipcp_close(f->unit, "Interface configuration failed"); - return; - } -#endif - sifnpmode(f->unit, PPP_IP, NPMODE_PASS); - - /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) - if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) - default_route_set[f->unit] = 1; - - /* Make a proxy ARP entry if requested. */ - if (ipcp_wantoptions[f->unit].proxy_arp) - if (sifproxyarp(f->unit, ho->hisaddr)) - proxy_arp_set[f->unit] = 1; - - syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr)); - syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr)); - } - - /* - * Execute the ip-up script, like this: - * /etc/ppp/ip-up interface tty speed local-IP remote-IP - */ - ipcp_script(f, _PATH_IPUP); - -} - - -/* - * ipcp_down - IPCP has gone DOWN. - * - * Take the IP network interface down, clear its addresses - * and delete routes through it. - */ -static void -ipcp_down(f) - fsm *f; -{ - IPCPDEBUG((LOG_INFO, "ipcp: down")); - np_down(f->unit, PPP_IP); - sifvjcomp(f->unit, 0, 0, 0); - - /* - * If we are doing dial-on-demand, set the interface - * to queue up outgoing packets (for now). - */ - if (demand) { - sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE); - } else { - sifdown(f->unit); - ipcp_clear_addrs(f->unit); - } - - /* Execute the ip-down script */ - ipcp_script(f, _PATH_IPDOWN); -} - - -/* - * ipcp_clear_addrs() - clear the interface addresses, routes, - * proxy arp entries, etc. - */ -static void -ipcp_clear_addrs(unit) - int unit; -{ - u_int32_t ouraddr, hisaddr; - - ouraddr = ipcp_gotoptions[unit].ouraddr; - hisaddr = ipcp_hisoptions[unit].hisaddr; - if (proxy_arp_set[unit]) { - cifproxyarp(unit, hisaddr); - proxy_arp_set[unit] = 0; - } - if (default_route_set[unit]) { - cifdefaultroute(unit, ouraddr, hisaddr); - default_route_set[unit] = 0; - } - cifaddr(unit, ouraddr, hisaddr); -} - - -/* - * ipcp_finished - possibly shut down the lower layers. - */ -static void -ipcp_finished(f) - fsm *f; -{ - np_finished(f->unit, PPP_IP); -} - - -/* - * ipcp_script - Execute a script with arguments - * interface-name tty-name speed local-IP remote-IP. - */ -static void -ipcp_script(f, script) - fsm *f; - char *script; -{ - char strspeed[32], strlocal[32], strremote[32]; - char *argv[8]; - - sprintf(strspeed, "%d", baud_rate); - strcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr)); - strcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr)); - - argv[0] = script; - argv[1] = ifname; - argv[2] = devnam; - argv[3] = strspeed; - argv[4] = strlocal; - argv[5] = strremote; - argv[6] = ipparam; - argv[7] = NULL; - run_program(script, argv, 0); -} - -/* - * ipcp_printpkt - print the contents of an IPCP packet. - */ -static char *ipcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej" -}; - -static int -ipcp_printpkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer)(void *, char *, ...); - void *arg; -{ - int code, id, len, olen; - u_char *pstart, *optend; - u_short cishort; - u_int32_t cilong; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *)) - printer(arg, " %s", ipcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_ADDRS: - if (olen == CILEN_ADDRS) { - p += 2; - GETLONG(cilong, p); - printer(arg, "addrs %I", htonl(cilong)); - GETLONG(cilong, p); - printer(arg, " %I", htonl(cilong)); - } - break; - case CI_COMPRESSTYPE: - if (olen >= CILEN_COMPRESS) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "compress "); - switch (cishort) { - case IPCP_VJ_COMP: - printer(arg, "VJ"); - break; - case IPCP_VJ_COMP_OLD: - printer(arg, "old-VJ"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_ADDR: - if (olen == CILEN_ADDR) { - p += 2; - GETLONG(cilong, p); - printer(arg, "addr %I", htonl(cilong)); - } - break; - case CI_MS_DNS1: - case CI_MS_DNS2: - p += 2; - GETLONG(cilong, p); - printer(arg, "ms-dns %I", htonl(cilong)); - break; - case CI_MS_WINS1: - case CI_MS_WINS2: - p += 2; - GETLONG(cilong, p); - printer(arg, "ms-wins %I", htonl(cilong)); - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} - -/* - * ip_active_pkt - see if this IP packet is worth bringing the link up for. - * We don't bring the link up for IP fragments or for TCP FIN packets - * with no data. - */ -#define IP_HDRLEN 20 /* bytes */ -#define IP_OFFMASK 0x1fff -#define IPPROTO_TCP 6 -#define TCP_HDRLEN 20 -#define TH_FIN 0x01 - -/* - * We use these macros because the IP header may be at an odd address, - * and some compilers might use word loads to get th_off or ip_hl. - */ - -#define net_short(x) (((x)[0] << 8) + (x)[1]) -#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) -#define get_ipoff(x) net_short((unsigned char *)(x) + 6) -#define get_ipproto(x) (((unsigned char *)(x))[9]) -#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) -#define get_tcpflags(x) (((unsigned char *)(x))[13]) - -static int -ip_active_pkt(pkt, len) - u_char *pkt; - int len; -{ - u_char *tcp; - int hlen; - - len -= PPP_HDRLEN; - pkt += PPP_HDRLEN; - if (len < IP_HDRLEN) - return 0; - if ((get_ipoff(pkt) & IP_OFFMASK) != 0) - return 0; - if (get_ipproto(pkt) != IPPROTO_TCP) - return 1; - hlen = get_iphl(pkt) * 4; - if (len < hlen + TCP_HDRLEN) - return 0; - tcp = pkt + hlen; - if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) - return 0; - return 1; -} diff --git a/usr.sbin/pppd/ipcp.h b/usr.sbin/pppd/ipcp.h deleted file mode 100644 index 73f8b7e..0000000 --- a/usr.sbin/pppd/ipcp.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * ipcp.h - IP Control Protocol definitions. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * Options. - */ -#define CI_ADDRS 1 /* IP Addresses */ -#define CI_COMPRESSTYPE 2 /* Compression Type */ -#define CI_ADDR 3 - -#define CI_MS_DNS1 129 /* Primary DNS value */ -#define CI_MS_WINS1 130 /* Primary WINS value */ -#define CI_MS_DNS2 131 /* Secondary DNS value */ -#define CI_MS_WINS2 132 /* Secondary WINS value */ - -#define MAX_STATES 16 /* from slcompress.h */ - -#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ -#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ -#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ - /* maxslot and slot number compression) */ - -#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ -#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ - /* compression option*/ - -typedef struct ipcp_options { - int neg_addr : 1; /* Negotiate IP Address? */ - int old_addrs : 1; /* Use old (IP-Addresses) option? */ - int req_addr : 1; /* Ask peer to send IP address? */ - int default_route : 1; /* Assign default route through interface? */ - int proxy_arp : 1; /* Make proxy ARP entry for peer? */ - int neg_vj : 1; /* Van Jacobson Compression? */ - int old_vj : 1; /* use old (short) form of VJ option? */ - int accept_local : 1; /* accept peer's value for ouraddr */ - int accept_remote : 1; /* accept peer's value for hisaddr */ - u_short vj_protocol; /* protocol value to use in VJ option */ - u_char maxslotindex, cflag; /* values for RFC1332 VJ compression neg. */ - u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ - u_int32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ - u_int32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ -} ipcp_options; - -extern fsm ipcp_fsm[]; -extern ipcp_options ipcp_wantoptions[]; -extern ipcp_options ipcp_gotoptions[]; -extern ipcp_options ipcp_allowoptions[]; -extern ipcp_options ipcp_hisoptions[]; - -char *ip_ntoa(u_int32_t); - -extern struct protent ipcp_protent; diff --git a/usr.sbin/pppd/ipv6cp.c b/usr.sbin/pppd/ipv6cp.c deleted file mode 100644 index 27ba3a9..0000000 --- a/usr.sbin/pppd/ipv6cp.c +++ /dev/null @@ -1,1422 +0,0 @@ -/* - ipv6cp.c - PPP IPV6 Control Protocol. - Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi> - - 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. 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. -*/ - -/* Original version, based on RFC2023 : - - Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt - Économique ayant pour membres BULL S.A. et l'INRIA). - - Ce logiciel informatique est disponible aux conditions - usuelles dans la recherche, c'est-à-dire qu'il peut - être utilisé, copié, modifié, distribué à l'unique - condition que ce texte soit conservé afin que - l'origine de ce logiciel soit reconnue. - - Le nom de l'Institut National de Recherche en Informatique - et en Automatique (INRIA), de l'IMAG, ou d'une personne morale - ou physique ayant participé à l'élaboration de ce logiciel ne peut - être utilisé sans son accord préalable explicite. - - Ce logiciel est fourni tel quel sans aucune garantie, - support ou responsabilité d'aucune sorte. - Ce logiciel est dérivé de sources d'origine - "University of California at Berkeley" et - "Digital Equipment Corporation" couvertes par des copyrights. - - L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) - est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National - Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant - sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). - - This work has been done in the context of GIE DYADE (joint R & D venture - between BULL S.A. and INRIA). - - This software is available with usual "research" terms - with the aim of retain credits of the software. - Permission to use, copy, modify and distribute this software for any - purpose and without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies, - and the name of INRIA, IMAG, or any contributor not be used in advertising - or publicity pertaining to this material without the prior explicit - permission. The software is provided "as is" without any - warranties, support or liabilities of any kind. - This software is derived from source code from - "University of California at Berkeley" and - "Digital Equipment Corporation" protected by copyrights. - - Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) - is a federation of seven research units funded by the CNRS, National - Polytechnic Institute of Grenoble and University Joseph Fourier. - The research unit in Software, Systems, Networks (LSR) is member of IMAG. -*/ - -/* - * Derived from : - * - * - * ipcp.c - PPP IP Control Protocol. - * - * 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: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $ - */ - -#ifndef lint -#define RCSID "$Id: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $" -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * TODO: - * - * Proxy Neighbour Discovery. - * - * Better defines for selecting the ordering of - * interface up / set address. (currently checks for __linux__, - * since SVR4 && (SNI || __USLC__) didn't work properly) - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <netdb.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "pppd.h" -#include "fsm.h" -#include "ipcp.h" -#include "ipv6cp.h" -#include "magic.h" -#include "pathnames.h" - -#define s6_addr32 __u6_addr.__u6_addr32 - -#ifdef RCSID -static const char rcsid[] = RCSID; -#endif - -/* global vars */ -ipv6cp_options ipv6cp_wantoptions[NUM_PPP]; /* Options that we want to request */ -ipv6cp_options ipv6cp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -ipv6cp_options ipv6cp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -ipv6cp_options ipv6cp_hisoptions[NUM_PPP]; /* Options that we ack'd */ -int no_ifaceid_neg = 0; - -/* local vars */ -static int ipv6cp_is_up; - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipv6cp_resetci(fsm *); /* Reset our CI */ -static int ipv6cp_cilen(fsm *); /* Return length of our CI */ -static void ipv6cp_addci(fsm *, u_char *, int *); /* Add our CI */ -static int ipv6cp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */ -static int ipv6cp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */ -static int ipv6cp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */ -static int ipv6cp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */ -static void ipv6cp_up(fsm *); /* We're UP */ -static void ipv6cp_down(fsm *); /* We're DOWN */ -static void ipv6cp_finished(fsm *); /* Don't need lower layer */ - -fsm ipv6cp_fsm[NUM_PPP]; /* IPV6CP fsm structure */ - -static fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ - ipv6cp_resetci, /* Reset our Configuration Information */ - ipv6cp_cilen, /* Length of our Configuration Information */ - ipv6cp_addci, /* Add our Configuration Information */ - ipv6cp_ackci, /* ACK our Configuration Information */ - ipv6cp_nakci, /* NAK our Configuration Information */ - ipv6cp_rejci, /* Reject our Configuration Information */ - ipv6cp_reqci, /* Request peer's Configuration Information */ - ipv6cp_up, /* Called when fsm reaches OPENED state */ - ipv6cp_down, /* Called when fsm leaves OPENED state */ - NULL, /* Called when we want the lower layer up */ - ipv6cp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPV6CP" /* String name of protocol */ -}; - - -/* - * Protocol entry points from main code. - */ -static void ipv6cp_init(int); -static void ipv6cp_open(int); -static void ipv6cp_close(int, char *); -static void ipv6cp_lowerup(int); -static void ipv6cp_lowerdown(int); -static void ipv6cp_input(int, u_char *, int); -static void ipv6cp_protrej(int); -static int ipv6cp_printpkt(u_char *, int, - void (*)(void *, char *, ...), void *); -static void ipv6_check_options(void); -static int ipv6_demand_conf(int); -static int ipv6_active_pkt(u_char *, int); - -struct protent ipv6cp_protent = { - PPP_IPV6CP, - ipv6cp_init, - ipv6cp_input, - ipv6cp_protrej, - ipv6cp_lowerup, - ipv6cp_lowerdown, - ipv6cp_open, - ipv6cp_close, - ipv6cp_printpkt, - NULL, - 0, - "IPV6CP", - ipv6_check_options, - ipv6_demand_conf, - ipv6_active_pkt -}; - -static void ipv6cp_clear_addrs(int, eui64_t, eui64_t); -static void ipv6cp_script(char *); - -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ -#define CILEN_IFACEID 10 /* RFC2472, interface identifier */ - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -/* - * This state variable is used to ensure that we don't - * run an ipcp-up/down script while one is already running. - */ -static enum script_state { - s_down, - s_up, -} ipv6cp_script_state; - -/* - * setifaceid - set the interface identifiers manually - */ -int -setifaceid(argv) - char **argv; -{ - char *comma, *arg; - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - struct in6_addr addr; - -#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ - (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) - - arg = *argv; - if ((comma = strchr(arg, ',')) == NULL) - comma = arg + strlen(arg); - - /* - * If comma first character, then no local identifier - */ - if (comma != arg) { - *comma = '\0'; - - if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { - option_error("Illegal interface identifier (local): %s", arg); - return 0; - } - - eui64_copy(addr.s6_addr32[2], wo->ourid); - wo->opt_local = 1; - *comma = ','; - } - - /* - * If comma last character, the no remote identifier - */ - if (*comma != 0 && *++comma != '\0') { - if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) { - option_error("Illegal interface identifier (remote): %s", comma); - return 0; - } - eui64_copy(addr.s6_addr32[2], wo->hisid); - wo->opt_remote = 1; - } - - ipv6cp_protent.enabled_flag = 1; - return 1; -} - -/* - * Make a string representation of a network address. - */ -char * -llv6_ntoa(ifaceid) - eui64_t ifaceid; -{ - static char b[64]; - - sprintf(b, "fe80::%s", eui64_ntoa(ifaceid)); - return b; -} - - -/* - * ipv6cp_init - Initialize IPV6CP. - */ -static void -ipv6cp_init(unit) - int unit; -{ - fsm *f = &ipv6cp_fsm[unit]; - ipv6cp_options *wo = &ipv6cp_wantoptions[unit]; - ipv6cp_options *ao = &ipv6cp_allowoptions[unit]; - - f->unit = unit; - f->protocol = PPP_IPV6CP; - f->callbacks = &ipv6cp_callbacks; - fsm_init(&ipv6cp_fsm[unit]); - - memset(wo, 0, sizeof(*wo)); - memset(ao, 0, sizeof(*ao)); - - wo->accept_local = 1; - wo->neg_ifaceid = 1; - ao->neg_ifaceid = 1; - -#ifdef IPV6CP_COMP - wo->neg_vj = 1; - ao->neg_vj = 1; - wo->vj_protocol = IPV6CP_COMP; -#endif - -} - - -/* - * ipv6cp_open - IPV6CP is allowed to come up. - */ -static void -ipv6cp_open(unit) - int unit; -{ - fsm_open(&ipv6cp_fsm[unit]); -} - - -/* - * ipv6cp_close - Take IPV6CP down. - */ -static void -ipv6cp_close(unit, reason) - int unit; - char *reason; -{ - fsm_close(&ipv6cp_fsm[unit], reason); -} - - -/* - * ipv6cp_lowerup - The lower layer is up. - */ -static void -ipv6cp_lowerup(unit) - int unit; -{ - fsm_lowerup(&ipv6cp_fsm[unit]); -} - - -/* - * ipv6cp_lowerdown - The lower layer is down. - */ -static void -ipv6cp_lowerdown(unit) - int unit; -{ - fsm_lowerdown(&ipv6cp_fsm[unit]); -} - - -/* - * ipv6cp_input - Input IPV6CP packet. - */ -static void -ipv6cp_input(unit, p, len) - int unit; - u_char *p; - int len; -{ - fsm_input(&ipv6cp_fsm[unit], p, len); -} - - -/* - * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void -ipv6cp_protrej(unit) - int unit; -{ - fsm_lowerdown(&ipv6cp_fsm[unit]); -} - - -/* - * ipv6cp_resetci - Reset our CI. - */ -static void -ipv6cp_resetci(f) - fsm *f; -{ - ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - - wo->req_ifaceid = wo->neg_ifaceid && ipv6cp_allowoptions[f->unit].neg_ifaceid; - - if (!wo->opt_local) { - eui64_magic_nz(wo->ourid); - } - - *go = *wo; - eui64_zero(go->hisid); /* last proposed interface identifier */ -} - - -/* - * ipv6cp_cilen - Return length of our CI. - */ -static int -ipv6cp_cilen(f) - fsm *f; -{ - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - -#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) -#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) - - return (LENCIIFACEID(go->neg_ifaceid) + - LENCIVJ(go->neg_vj)); -} - - -/* - * ipv6cp_addci - Add our desired CIs to a packet. - */ -static void -ipv6cp_addci(f, ucp, lenp) - fsm *f; - u_char *ucp; - int *lenp; -{ - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - int len = *lenp; - -#define ADDCIVJ(opt, neg, val) \ - if (neg) { \ - int vjlen = CILEN_COMPRESS; \ - if (len >= vjlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(vjlen, ucp); \ - PUTSHORT(val, ucp); \ - len -= vjlen; \ - } else \ - neg = 0; \ - } - -#define ADDCIIFACEID(opt, neg, val1) \ - if (neg) { \ - int idlen = CILEN_IFACEID; \ - if (len >= idlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(idlen, ucp); \ - eui64_put(val1, ucp); \ - len -= idlen; \ - } else \ - neg = 0; \ - } - - ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); - - ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); - - *lenp -= len; -} - - -/* - * ipv6cp_ackci - Ack our CIs. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int -ipv6cp_ackci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - u_short cilen, citype, cishort; - eui64_t ifaceid; - - /* - * CIs must be in exactly the same order that we sent... - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - -#define ACKCIVJ(opt, neg, val) \ - if (neg) { \ - int vjlen = CILEN_COMPRESS; \ - if ((len -= vjlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != vjlen || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - } - -#define ACKCIIFACEID(opt, neg, val1) \ - if (neg) { \ - int idlen = CILEN_IFACEID; \ - if ((len -= idlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != idlen || \ - citype != opt) \ - goto bad; \ - eui64_get(ifaceid, p); \ - if (! eui64_equals(val1, ifaceid)) \ - goto bad; \ - } - - ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); - - ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); - -bad: - IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); - return (0); -} - -/* - * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPV6CP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int -ipv6cp_nakci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - u_char citype, cilen, *next; - u_short cishort; - eui64_t ifaceid; - ipv6cp_options no; /* options we've seen Naks for */ - ipv6cp_options try; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIIFACEID(opt, neg, code) \ - if (go->neg && \ - len >= (cilen = CILEN_IFACEID) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - eui64_get(ifaceid, p); \ - no.neg = 1; \ - code \ - } - -#define NAKCIVJ(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_COMPRESS) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } - - /* - * Accept the peer's idea of {our,his} interface identifier, if different - * from our idea, only if the accept_{local,remote} flag is set. - */ - NAKCIIFACEID(CI_IFACEID, neg_ifaceid, - if (go->accept_local) { - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->hisid)) /* bad luck */ - eui64_magic(ifaceid); - try.ourid = ifaceid; - IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); - } - ); - -#ifdef IPV6CP_COMP - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - { - if (cishort == IPV6CP_COMP) { - try.vj_protocol = cishort; - } else { - try.neg_vj = 0; - } - } - ); -#else - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - { - try.neg_vj = 0; - } - ); -#endif - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If they want to negotiate about interface identifier, we comply. - * If they want us to ask for compression, we refuse. - */ - while (len > CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if( (len -= cilen) < 0 ) - goto bad; - next = p + cilen - 2; - - switch (citype) { - case CI_COMPRESSTYPE: - if (go->neg_vj || no.neg_vj || - (cilen != CILEN_COMPRESS)) - goto bad; - no.neg_vj = 1; - break; - case CI_IFACEID: - if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) - goto bad; - try.neg_ifaceid = 1; - eui64_get(ifaceid, p); - if (go->accept_local) { - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->hisid)) /* bad luck */ - eui64_magic(ifaceid); - try.ourid = ifaceid; - } - no.neg_ifaceid = 1; - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) - goto bad; - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != OPENED) - *go = try; - - return 1; - -bad: - IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); - return 0; -} - - -/* - * ipv6cp_rejci - Reject some of our CIs. - */ -static int -ipv6cp_rejci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - u_char cilen; - u_short cishort; - eui64_t ifaceid; - ipv6cp_options try; /* options to request next time */ - - try = *go; - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIIFACEID(opt, neg, val1) \ - if (go->neg && \ - len >= (cilen = CILEN_IFACEID) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - eui64_get(ifaceid, p); \ - /* Check rejected value. */ \ - if (! eui64_equals(ifaceid, val1)) \ - goto bad; \ - try.neg = 0; \ - } - -#define REJCIVJ(opt, neg, val) \ - if (go->neg && \ - p[1] == CILEN_COMPRESS && \ - len >= p[1] && \ - p[0] == opt) { \ - len -= p[1]; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - try.neg = 0; \ - } - - REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); - - REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != OPENED) - *go = try; - return 1; - -bad: - IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); - return 0; -} - - -/* - * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - */ -static int -ipv6cp_reqci(f, inp, len, reject_if_disagree) - fsm *f; - u_char *inp; /* Requested CIs */ - int *len; /* Length of requested CIs */ - int reject_if_disagree; -{ - ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; - ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit]; - ipv6cp_options *ao = &ipv6cp_allowoptions[f->unit]; - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ - u_short cishort; /* Parsed short value */ - eui64_t ifaceid; /* Parsed interface identifier */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_IFACEID: - IPV6CPDEBUG(("ipv6cp: received interface identifier ")); - - if (!ao->neg_ifaceid || - cilen != CILEN_IFACEID) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no interface identifier, or if we both have same - * identifier then NAK it with new idea. - * In particular, if we don't know his identifier, but he does, - * then accept it. - */ - eui64_get(ifaceid, p); - IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); - if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { - orc = CONFREJ; /* Reject CI */ - break; - } - if (!eui64_iszero(wo->hisid) && - !eui64_equals(ifaceid, wo->hisid) && - eui64_iszero(go->hisid)) { - - orc = CONFNAK; - ifaceid = wo->hisid; - go->hisid = ifaceid; - DECPTR(sizeof(ifaceid), p); - eui64_put(ifaceid, p); - } else - if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) { - orc = CONFNAK; - if (eui64_iszero(go->hisid)) /* first time, try option */ - ifaceid = wo->hisid; - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->ourid)) /* bad luck */ - eui64_magic(ifaceid); - go->hisid = ifaceid; - DECPTR(sizeof(ifaceid), p); - eui64_put(ifaceid, p); - } - - ho->neg_ifaceid = 1; - ho->hisid = ifaceid; - break; - - case CI_COMPRESSTYPE: - IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); - if (!ao->neg_vj || - (cilen != CILEN_COMPRESS)) { - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - IPV6CPDEBUG(("(%d)", cishort)); - -#ifdef IPV6CP_COMP - if (!(cishort == IPV6CP_COMP)) { - orc = CONFREJ; - break; - } -#else - orc = CONFREJ; - break; -#endif - - ho->neg_vj = 1; - ho->vj_protocol = cishort; - break; - - default: - orc = CONFREJ; - break; - } - -endswitch: - IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); - - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ - orc = CONFREJ; /* Get tough if so */ - else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) - BCOPY(cip, ucp, cilen); /* Move it */ - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their identifier and they didn't send their identifier, then we - * send a NAK with a CI_IFACEID option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - if (rc != CONFREJ && !ho->neg_ifaceid && - wo->req_ifaceid && !reject_if_disagree) { - if (rc == CONFACK) { - rc = CONFNAK; - ucp = inp; /* reset pointer */ - wo->req_ifaceid = 0; /* don't ask again */ - } - PUTCHAR(CI_IFACEID, ucp); - PUTCHAR(CILEN_IFACEID, ucp); - eui64_put(wo->hisid, ucp); - } - - *len = ucp - inp; /* Compute output length */ - IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -/* - * ipv6_check_options - check that any IP-related options are OK, - * and assign appropriate defaults. - */ -static void -ipv6_check_options() -{ - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - -#if defined(SOL2) - /* - * Persistent link-local id is only used when user has not explicitly - * configure/hard-code the id - */ - if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { - - /* - * On systems where there are no Ethernet interfaces used, there - * may be other ways to obtain a persistent id. Right now, it - * will fall back to using magic [see eui64_magic] below when - * an EUI-48 from MAC address can't be obtained. Other possibilities - * include obtaining EEPROM serial numbers, or some other unique - * yet persistent number. On Sparc platforms, this is possible, - * but too bad there's no standards yet for x86 machines. - */ - if (ether_to_eui64(&wo->ourid)) { - wo->opt_local = 1; - } - } -#endif - - if (!wo->opt_local) { /* init interface identifier */ - if (wo->use_ip && eui64_iszero(wo->ourid)) { - eui64_setlo32(wo->ourid, ntohl(ipcp_wantoptions[0].ouraddr)); - if (!eui64_iszero(wo->ourid)) - wo->opt_local = 1; - } - - while (eui64_iszero(wo->ourid)) - eui64_magic(wo->ourid); - } - - if (!wo->opt_remote) { - if (wo->use_ip && eui64_iszero(wo->hisid)) { - eui64_setlo32(wo->hisid, ntohl(ipcp_wantoptions[0].hisaddr)); - if (!eui64_iszero(wo->hisid)) - wo->opt_remote = 1; - } - } - - if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { - option_error("local/remote LL address required for demand-dialling\n"); - exit(1); - } -} - - -/* - * ipv6_demand_conf - configure the interface as though - * IPV6CP were up, for use with dial-on-demand. - */ -static int -ipv6_demand_conf(u) - int u; -{ - ipv6cp_options *wo = &ipv6cp_wantoptions[u]; - -#if defined(__linux__) || defined(SOL2) || (defined(SVR4) && (defined(SNI) || defined(__USLC__))) -#if defined(SOL2) - if (!sif6up(u)) - return 0; -#else - if (!sifup(u)) - return 0; -#endif /* defined(SOL2) */ -#endif - if (!sif6addr(u, wo->ourid, wo->hisid)) - return 0; -#if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sifup(u)) - return 0; -#endif - if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) - return 0; - - syslog(LOG_NOTICE, "ipv6_demand_conf"); - syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(wo->ourid)); - syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(wo->hisid)); - - return 1; -} - - -/* - * ipv6cp_up - IPV6CP has come UP. - * - * Configure the IPv6 network interface appropriately and bring it up. - */ -static void -ipv6cp_up(f) - fsm *f; -{ - ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit]; - ipv6cp_options *go = &ipv6cp_gotoptions[f->unit]; - ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit]; - - IPV6CPDEBUG(("ipv6cp: up")); - - /* - * We must have a non-zero LL address for both ends of the link. - */ - if (!ho->neg_ifaceid) - ho->hisid = wo->hisid; - - if(!no_ifaceid_neg) { - if (eui64_iszero(ho->hisid)) { - syslog(LOG_ERR, "Could not determine remote LL address"); - ipv6cp_close(f->unit, "Could not determine remote LL address"); - return; - } - if (eui64_iszero(go->ourid)) { - syslog(LOG_ERR, "Could not determine local LL address"); - ipv6cp_close(f->unit, "Could not determine local LL address"); - return; - } - if (eui64_equals(go->ourid, ho->hisid)) { - syslog(LOG_ERR, "local and remote LL addresses are equal"); - ipv6cp_close(f->unit, "local and remote LL addresses are equal"); - return; - } - } - script_setenv("LLLOCAL", llv6_ntoa(go->ourid)); - script_setenv("LLREMOTE", llv6_ntoa(ho->hisid)); - -#ifdef IPV6CP_COMP - /* set tcp compression */ - sif6comp(f->unit, ho->neg_vj); -#endif - - /* - * If we are doing dial-on-demand, the interface is already - * configured, so we put out any saved-up packets, then set the - * interface to pass IPv6 packets. - */ - if (demand) { - if (! eui64_equals(go->ourid, wo->ourid) || - ! eui64_equals(ho->hisid, wo->hisid)) { - if (! eui64_equals(go->ourid, wo->ourid)) - warn("Local LL address changed to %s", - llv6_ntoa(go->ourid)); - if (! eui64_equals(ho->hisid, wo->hisid)) - warn("Remote LL address changed to %s", - llv6_ntoa(ho->hisid)); - ipv6cp_clear_addrs(f->unit, go->ourid, ho->hisid); - - /* Set the interface to the new addresses */ - if (!sif6addr(f->unit, go->ourid, ho->hisid)) { - if (debug) - warn("sif6addr failed"); - ipv6cp_close(f->unit, "Interface configuration failed"); - return; - } - - } - demand_rexmit(PPP_IPV6); - sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); - - } else { - /* - * Set LL addresses - */ -#if !defined(__linux__) && !defined(SOL2) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sif6addr(f->unit, go->ourid, ho->hisid)) { - if (debug) - warn("sif6addr failed"); - ipv6cp_close(f->unit, "Interface configuration failed"); - return; - } -#endif - - /* bring the interface up for IPv6 */ -#if defined(SOL2) - if (!sif6up(f->unit)) { - if (debug) - warn("sifup failed (IPV6)"); - ipv6cp_close(f->unit, "Interface configuration failed"); - return; - } -#else - if (!sifup(f->unit)) { - if (debug) - warn("sifup failed (IPV6)"); - ipv6cp_close(f->unit, "Interface configuration failed"); - return; - } -#endif /* defined(SOL2) */ - -#if defined(__linux__) || defined(SOL2) || (defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sif6addr(f->unit, go->ourid, ho->hisid)) { - if (debug) - warn("sif6addr failed"); - ipv6cp_close(f->unit, "Interface configuration failed"); - return; - } -#endif - sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); - - syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(go->ourid)); - syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(ho->hisid)); - } - - np_up(f->unit, PPP_IPV6); - ipv6cp_is_up = 1; - - /* - * Execute the ipv6-up script, like this: - * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL - */ - if (ipv6cp_script_state == s_down) { - ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); - } -} - - -/* - * ipv6cp_down - IPV6CP has gone DOWN. - * - * Take the IPv6 network interface down, clear its addresses - * and delete routes through it. - */ -static void -ipv6cp_down(f) - fsm *f; -{ - IPV6CPDEBUG(("ipv6cp: down")); - if (ipv6cp_is_up) { - ipv6cp_is_up = 0; - np_down(f->unit, PPP_IPV6); - } -#ifdef IPV6CP_COMP - sif6comp(f->unit, 0); -#endif - - /* - * If we are doing dial-on-demand, set the interface - * to queue up outgoing packets (for now). - */ - if (demand) { - sifnpmode(f->unit, PPP_IPV6, NPMODE_QUEUE); - } else { - sifnpmode(f->unit, PPP_IPV6, NPMODE_DROP); -#if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC))) -#if defined(SOL2) - sif6down(f->unit); -#else - sifdown(f->unit); -#endif /* defined(SOL2) */ -#endif - ipv6cp_clear_addrs(f->unit, - ipv6cp_gotoptions[f->unit].ourid, - ipv6cp_hisoptions[f->unit].hisid); -#if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC))) - sifdown(f->unit); -#endif - } - - /* Execute the ipv6-down script */ - if (ipv6cp_script_state == s_up) { - ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); - } -} - - -/* - * ipv6cp_clear_addrs() - clear the interface addresses, routes, - * proxy neighbour discovery entries, etc. - */ -static void -ipv6cp_clear_addrs(unit, ourid, hisid) - int unit; - eui64_t ourid; - eui64_t hisid; -{ - cif6addr(unit, ourid, hisid); -} - - -/* - * ipv6cp_finished - possibly shut down the lower layers. - */ -static void -ipv6cp_finished(f) - fsm *f; -{ - np_finished(f->unit, PPP_IPV6); -} - - -/* - * ipv6cp_script - Execute a script with arguments - * interface-name tty-name speed local-LL remote-LL. - */ -static void -ipv6cp_script(script) - char *script; -{ - char strspeed[32], strlocal[32], strremote[32]; - char *argv[8]; - - sprintf(strspeed, "%d", baud_rate); - strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid)); - strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid)); - - argv[0] = script; - argv[1] = ifname; - argv[2] = devnam; - argv[3] = strspeed; - argv[4] = strlocal; - argv[5] = strremote; - argv[6] = ipparam; - argv[7] = NULL; - - run_program(script, argv, 0); -} - -/* - * ipv6cp_printpkt - print the contents of an IPV6CP packet. - */ -static char *ipv6cp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej" -}; - -static int -ipv6cp_printpkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer)(void *, char *, ...); - void *arg; -{ - int code, id, len, olen; - u_char *pstart, *optend; - u_short cishort; - eui64_t ifaceid; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(ipv6cp_codenames) / sizeof(char *)) - printer(arg, " %s", ipv6cp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_COMPRESSTYPE: - if (olen >= CILEN_COMPRESS) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "compress "); - printer(arg, "0x%x", cishort); - } - break; - case CI_IFACEID: - if (olen == CILEN_IFACEID) { - p += 2; - eui64_get(ifaceid, p); - printer(arg, "addr %s", llv6_ntoa(ifaceid)); - } - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} - -/* - * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. - * We don't bring the link up for IP fragments or for TCP FIN packets - * with no data. - */ -#define IP6_HDRLEN 40 /* bytes */ -#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */ -#define IPPROTO_TCP 6 -#define TCP_HDRLEN 20 -#define TH_FIN 0x01 - -/* - * We use these macros because the IP header may be at an odd address, - * and some compilers might use word loads to get th_off or ip_hl. - */ - -#define get_ip6nh(x) (((unsigned char *)(x))[6]) -#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) -#define get_tcpflags(x) (((unsigned char *)(x))[13]) - -static int -ipv6_active_pkt(pkt, len) - u_char *pkt; - int len; -{ - u_char *tcp; - - len -= PPP_HDRLEN; - pkt += PPP_HDRLEN; - if (len < IP6_HDRLEN) - return 0; - if (get_ip6nh(pkt) == IP6_NHDR_FRAG) - return 0; - if (get_ip6nh(pkt) != IPPROTO_TCP) - return 1; - if (len < IP6_HDRLEN + TCP_HDRLEN) - return 0; - tcp = pkt + IP6_HDRLEN; - if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4) - return 0; - return 1; -} diff --git a/usr.sbin/pppd/ipv6cp.h b/usr.sbin/pppd/ipv6cp.h deleted file mode 100644 index 39f9444..0000000 --- a/usr.sbin/pppd/ipv6cp.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - ipv6cp.h - PPP IPV6 Control Protocol. - Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi> - - 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. 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. -*/ - -/* Original version, based on RFC2023 : - - Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt - Économique ayant pour membres BULL S.A. et l'INRIA). - - Ce logiciel informatique est disponible aux conditions - usuelles dans la recherche, c'est-à-dire qu'il peut - être utilisé, copié, modifié, distribué à l'unique - condition que ce texte soit conservé afin que - l'origine de ce logiciel soit reconnue. - - Le nom de l'Institut National de Recherche en Informatique - et en Automatique (INRIA), de l'IMAG, ou d'une personne morale - ou physique ayant participé à l'élaboration de ce logiciel ne peut - être utilisé sans son accord préalable explicite. - - Ce logiciel est fourni tel quel sans aucune garantie, - support ou responsabilité d'aucune sorte. - Ce logiciel est dérivé de sources d'origine - "University of California at Berkeley" et - "Digital Equipment Corporation" couvertes par des copyrights. - - L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) - est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National - Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant - sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). - - This work has been done in the context of GIE DYADE (joint R & D venture - between BULL S.A. and INRIA). - - This software is available with usual "research" terms - with the aim of retain credits of the software. - Permission to use, copy, modify and distribute this software for any - purpose and without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies, - and the name of INRIA, IMAG, or any contributor not be used in advertising - or publicity pertaining to this material without the prior explicit - permission. The software is provided "as is" without any - warranties, support or liabilities of any kind. - This software is derived from source code from - "University of California at Berkeley" and - "Digital Equipment Corporation" protected by copyrights. - - Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) - is a federation of seven research units funded by the CNRS, National - Polytechnic Institute of Grenoble and University Joseph Fourier. - The research unit in Software, Systems, Networks (LSR) is member of IMAG. -*/ - -/* - * Derived from : - * - * - * ipcp.h - IP Control Protocol definitions. - * - * Copyright (c) 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: ipv6cp.h,v 1.3 1999/09/30 19:57:45 masputra Exp $ - * $FreeBSD$ - */ - -/* - * Options. - */ -#define CI_IFACEID 1 /* Interface Identifier */ -#define CI_COMPRESSTYPE 2 /* Compression Type */ - -/* No compression types yet defined. - *#define IPV6CP_COMP 0x004f - */ -typedef struct ipv6cp_options { - int neg_ifaceid; /* Negotiate interface identifier? */ - int req_ifaceid; /* Ask peer to send interface identifier? */ - int accept_local; /* accept peer's value for iface id? */ - int opt_local; /* ourtoken set by option */ - int opt_remote; /* histoken set by option */ - int use_ip; /* use IP as interface identifier */ -#if defined(SOL2) - int use_persistent; /* use uniquely persistent value for address */ -#endif /* defined(SOL2) */ - int neg_vj; /* Van Jacobson Compression? */ - u_short vj_protocol; /* protocol value to use in VJ option */ - eui64_t ourid, hisid; /* Interface identifiers */ -} ipv6cp_options; - -extern fsm ipv6cp_fsm[]; -extern ipv6cp_options ipv6cp_wantoptions[]; -extern ipv6cp_options ipv6cp_gotoptions[]; -extern ipv6cp_options ipv6cp_allowoptions[]; -extern ipv6cp_options ipv6cp_hisoptions[]; - -extern struct protent ipv6cp_protent; - -extern int setifaceid(char **arg); diff --git a/usr.sbin/pppd/ipxcp.c b/usr.sbin/pppd/ipxcp.c deleted file mode 100644 index ea7f127..0000000 --- a/usr.sbin/pppd/ipxcp.c +++ /dev/null @@ -1,1399 +0,0 @@ -/* - * ipxcp.c - PPP IPX Control Protocol. - * - * 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. - */ - -#ifdef IPX_CHANGE -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -/* - * TODO: - */ - -#include <stdio.h> -#include <string.h> -#include <syslog.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> - -#include "pppd.h" -#include "fsm.h" -#include "ipxcp.h" -#include "pathnames.h" - -/* global vars */ -ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */ -ipxcp_options ipxcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -ipxcp_options ipxcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -ipxcp_options ipxcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ - -#define wo (&ipxcp_wantoptions[0]) -#define ao (&ipxcp_allowoptions[0]) -#define go (&ipxcp_gotoptions[0]) -#define ho (&ipxcp_hisoptions[0]) - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipxcp_resetci(fsm *); /* Reset our CI */ -static int ipxcp_cilen(fsm *); /* Return length of our CI */ -static void ipxcp_addci(fsm *, u_char *, int *); /* Add our CI */ -static int ipxcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */ -static int ipxcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */ -static int ipxcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */ -static int ipxcp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */ -static void ipxcp_up(fsm *); /* We're UP */ -static void ipxcp_down(fsm *); /* We're DOWN */ -static void ipxcp_script(fsm *, char *); /* Run an up/down script */ - -fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */ - -static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */ - ipxcp_resetci, /* Reset our Configuration Information */ - ipxcp_cilen, /* Length of our Configuration Information */ - ipxcp_addci, /* Add our Configuration Information */ - ipxcp_ackci, /* ACK our Configuration Information */ - ipxcp_nakci, /* NAK our Configuration Information */ - ipxcp_rejci, /* Reject our Configuration Information */ - ipxcp_reqci, /* Request peer's Configuration Information */ - ipxcp_up, /* Called when fsm reaches OPENED state */ - ipxcp_down, /* Called when fsm leaves OPENED state */ - NULL, /* Called when we want the lower layer up */ - NULL, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPXCP" /* String name of protocol */ -}; - -/* - * Protocol entry points. - */ - -static void ipxcp_init(int); -static void ipxcp_open(int); -static void ipxcp_close(int, char *); -static void ipxcp_lowerup(int); -static void ipxcp_lowerdown(int); -static void ipxcp_input(int, u_char *, int); -static void ipxcp_protrej(int); -static int ipxcp_printpkt(u_char *, int, - void (*)(void *, char *, ...), void *); - -struct protent ipxcp_protent = { - PPP_IPXCP, - ipxcp_init, - ipxcp_input, - ipxcp_protrej, - ipxcp_lowerup, - ipxcp_lowerdown, - ipxcp_open, - ipxcp_close, - ipxcp_printpkt, - NULL, - 0, - "IPXCP", - NULL, - NULL, - NULL -}; - -/* - * Lengths of configuration options. - */ - -#define CILEN_VOID 2 -#define CILEN_COMPLETE 2 /* length of complete option */ -#define CILEN_NETN 6 /* network number length option */ -#define CILEN_NODEN 8 /* node number length option */ -#define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */ -#define CILEN_NAME 3 /* Minimum length of router name */ -#define CILEN_COMPRESS 4 /* Minimum length of compression protocol */ - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -/* Used in printing the node number */ -#define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5] - -/* Used to generate the proper bit mask */ -#define BIT(num) (1 << (num)) - -/* - * Convert from internal to external notation - */ - -static short int -to_external(internal) -short int internal; -{ - short int external; - - if (internal & IPX_NONE) - external = IPX_NONE; - else - external = RIP_SAP; - - return external; -} - -/* - * Make a string representation of a network IP address. - */ - -char * -ipx_ntoa(ipxaddr) -u_int32_t ipxaddr; -{ - static char b[64]; - sprintf(b, "%x", ipxaddr); - return b; -} - - -/* - * ipxcp_init - Initialize IPXCP. - */ -static void -ipxcp_init(unit) - int unit; -{ - fsm *f = &ipxcp_fsm[unit]; - - f->unit = unit; - f->protocol = PPP_IPXCP; - f->callbacks = &ipxcp_callbacks; - fsm_init(&ipxcp_fsm[unit]); - - memset (wo->name, 0, sizeof (wo->name)); - memset (wo->our_node, 0, sizeof (wo->our_node)); - memset (wo->his_node, 0, sizeof (wo->his_node)); - - wo->neg_nn = 1; - wo->neg_complete = 1; - wo->network = 0; - - ao->neg_node = 1; - ao->neg_nn = 1; - ao->neg_name = 1; - ao->neg_complete = 1; - ao->neg_router = 1; - - ao->accept_local = 0; - ao->accept_remote = 0; - ao->accept_network = 0; - - wo->tried_rip = 0; - wo->tried_nlsp = 0; -} - -/* - * Copy the node number - */ - -static void -copy_node (src, dst) -u_char *src, *dst; -{ - memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node)); -} - -/* - * Compare node numbers - */ - -static int -compare_node (src, dst) -u_char *src, *dst; -{ - return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0; -} - -/* - * Is the node number zero? - */ - -static int -zero_node (node) -u_char *node; -{ - int indx; - for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx) - if (node [indx] != 0) - return 0; - return 1; -} - -/* - * Increment the node number - */ - -static void -inc_node (node) -u_char *node; -{ - u_char *outp; - u_int32_t magic_num; - - outp = node; - magic_num = magic(); - *outp++ = '\0'; - *outp++ = '\0'; - PUTLONG (magic_num, outp); -} - -/* - * ipxcp_open - IPXCP is allowed to come up. - */ -static void -ipxcp_open(unit) - int unit; -{ - fsm_open(&ipxcp_fsm[unit]); -} - -/* - * ipxcp_close - Take IPXCP down. - */ -static void -ipxcp_close(unit, reason) - int unit; - char *reason; -{ - fsm_close(&ipxcp_fsm[unit], reason); -} - - -/* - * ipxcp_lowerup - The lower layer is up. - */ -static void -ipxcp_lowerup(unit) - int unit; -{ - fsm_lowerup(&ipxcp_fsm[unit]); -} - - -/* - * ipxcp_lowerdown - The lower layer is down. - */ -static void -ipxcp_lowerdown(unit) - int unit; -{ - fsm_lowerdown(&ipxcp_fsm[unit]); -} - - -/* - * ipxcp_input - Input IPXCP packet. - */ -static void -ipxcp_input(unit, p, len) - int unit; - u_char *p; - int len; -{ - fsm_input(&ipxcp_fsm[unit], p, len); -} - - -/* - * ipxcp_protrej - A Protocol-Reject was received for IPXCP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void -ipxcp_protrej(unit) - int unit; -{ - fsm_lowerdown(&ipxcp_fsm[unit]); -} - - -/* - * ipxcp_resetci - Reset our CI. - */ -static void -ipxcp_resetci(f) - fsm *f; -{ - wo->req_node = wo->neg_node && ao->neg_node; - wo->req_nn = wo->neg_nn && ao->neg_nn; - - if (wo->our_network == 0) { - wo->neg_node = 1; - ao->accept_network = 1; - } -/* - * If our node number is zero then change it. - */ - if (zero_node (wo->our_node)) { - inc_node (wo->our_node); - ao->accept_local = 1; - wo->neg_node = 1; - } -/* - * If his node number is zero then change it. - */ - if (zero_node (wo->his_node)) { - inc_node (wo->his_node); - ao->accept_remote = 1; - } -/* - * If no routing agent was specified then we do RIP/SAP according to the - * RFC documents. If you have specified something then OK. Otherwise, we - * do RIP/SAP. - */ - if (ao->router == 0) { - ao->router |= BIT(RIP_SAP); - wo->router |= BIT(RIP_SAP); - } - - /* Always specify a routing protocol unless it was REJected. */ - wo->neg_router = 1; -/* - * Start with these default values - */ - *go = *wo; -} - -/* - * ipxcp_cilen - Return length of our CI. - */ - -static int -ipxcp_cilen(f) - fsm *f; -{ - int len; - - len = go->neg_nn ? CILEN_NETN : 0; - len += go->neg_node ? CILEN_NODEN : 0; - len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0; - - /* RFC says that defaults should not be included. */ - if (go->neg_router && to_external(go->router) != RIP_SAP) - len += CILEN_PROTOCOL; - - return (len); -} - - -/* - * ipxcp_addci - Add our desired CIs to a packet. - */ -static void -ipxcp_addci(f, ucp, lenp) - fsm *f; - u_char *ucp; - int *lenp; -{ -/* - * Add the options to the record. - */ - if (go->neg_nn) { - PUTCHAR (IPX_NETWORK_NUMBER, ucp); - PUTCHAR (CILEN_NETN, ucp); - PUTLONG (go->our_network, ucp); - } - - if (go->neg_node) { - int indx; - PUTCHAR (IPX_NODE_NUMBER, ucp); - PUTCHAR (CILEN_NODEN, ucp); - for (indx = 0; indx < sizeof (go->our_node); ++indx) - PUTCHAR (go->our_node[indx], ucp); - } - - if (go->neg_name) { - int cilen = strlen (go->name); - int indx; - PUTCHAR (IPX_ROUTER_NAME, ucp); - PUTCHAR (CILEN_NAME + cilen - 1, ucp); - for (indx = 0; indx < cilen; ++indx) - PUTCHAR (go->name [indx], ucp); - } - - if (go->neg_router) { - short external = to_external (go->router); - if (external != RIP_SAP) { - PUTCHAR (IPX_ROUTER_PROTOCOL, ucp); - PUTCHAR (CILEN_PROTOCOL, ucp); - PUTSHORT (external, ucp); - } - } -} - -/* - * ipxcp_ackci - Ack our CIs. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int -ipxcp_ackci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - u_short cilen, citype, cishort; - u_char cichar; - u_int32_t cilong; - -#define ACKCIVOID(opt, neg) \ - if (neg) { \ - if ((len -= CILEN_VOID) < 0) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_VOID || \ - citype != opt) \ - break; \ - } - -#define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg) - -#define ACKCICHARS(opt, neg, val, cnt) \ - if (neg) { \ - int indx, count = cnt; \ - len -= (count + 2); \ - if (len < 0) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != (count + 2) || \ - citype != opt) \ - break; \ - for (indx = 0; indx < count; ++indx) {\ - GETCHAR(cichar, p); \ - if (cichar != ((u_char *) &val)[indx]) \ - break; \ - }\ - if (indx != count) \ - break; \ - } - -#define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val)) -#define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val)) - -#define ACKCINETWORK(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_NETN) < 0) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_NETN || \ - citype != opt) \ - break; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - break; \ - } - -#define ACKCIPROTO(opt, neg, val) \ - if (neg) { \ - if (len < 2) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_PROTOCOL || citype != opt) \ - break; \ - len -= cilen; \ - if (len < 0) \ - break; \ - GETSHORT(cishort, p); \ - if (cishort != to_external (val) || cishort == RIP_SAP) \ - break; \ - } -/* - * Process the ACK frame in the order in which the frame was assembled - */ - do { - ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network); - ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node); - ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name); - ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router); - ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router); - ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router); -/* - * This is the end of the record. - */ - if (len == 0) - return (1); - } while (0); -/* - * The frame is invalid - */ - IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!")); - return (0); -} - -/* - * ipxcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPXCP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ - -static int -ipxcp_nakci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - u_char citype, cilen, *next; - u_short s; - u_int32_t l; - ipxcp_options no; /* options we've seen Naks for */ - ipxcp_options try; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try = *go; - - while (len > CILEN_VOID) { - GETCHAR (citype, p); - GETCHAR (cilen, p); - len -= cilen; - if (len < 0) - goto bad; - next = &p [cilen - CILEN_VOID]; - - switch (citype) { - case IPX_NETWORK_NUMBER: - if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN)) - goto bad; - no.neg_nn = 1; - - GETLONG(l, p); - IPXCPDEBUG((LOG_INFO, "local IP address %d", l)); - if (l && ao->accept_network) - try.our_network = l; - break; - - case IPX_NODE_NUMBER: - if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN)) - goto bad; - no.neg_node = 1; - - IPXCPDEBUG((LOG_INFO, - "local node number %02X%02X%02X%02X%02X%02X", - NODE(p))); - - if (!zero_node (p) && ao->accept_local && - ! compare_node (p, ho->his_node)) - copy_node (p, try.our_node); - break; - - /* This has never been sent. Ignore the NAK frame */ - case IPX_COMPRESSION_PROTOCOL: - goto bad; - - case IPX_ROUTER_PROTOCOL: - if (!go->neg_router || (cilen < CILEN_PROTOCOL)) - goto bad; - - GETSHORT (s, p); - if (s > 15) /* This is just bad, but ignore for now. */ - break; - - s = BIT(s); - if (no.router & s) /* duplicate NAKs are always bad */ - goto bad; - - if (no.router == 0) /* Reset on first NAK only */ - try.router = 0; - - no.router |= s; - try.router |= s; - try.neg_router = 1; - - IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s)); - break; - - /* These, according to the RFC, must never be NAKed. */ - case IPX_ROUTER_NAME: - case IPX_COMPLETE: - goto bad; - - /* These are for options which we have not seen. */ - default: - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) - goto bad; - - /* - * Do not permit the peer to force a router protocol which we do not - * support. However, default to the condition that will accept "NONE". - */ - try.router &= (ao->router | BIT(IPX_NONE)); - if (try.router == 0 && ao->router != 0) - try.router = BIT(IPX_NONE); - - if (try.router != 0) - try.neg_router = 1; - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != OPENED) - *go = try; - - return 1; - -bad: - IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!")); - return 0; -} - -/* - * ipxcp_rejci - Reject some of our CIs. - */ -static int -ipxcp_rejci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - u_short cilen, citype, cishort; - u_char cichar; - u_int32_t cilong; - ipxcp_options try; /* options to request next time */ - -#define REJCINETWORK(opt, neg, val) \ - if (neg && p[0] == opt) { \ - if ((len -= CILEN_NETN) < 0) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_NETN || \ - citype != opt) \ - break; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - break; \ - IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \ - neg = 0; \ - } - -#define REJCICHARS(opt, neg, val, cnt) \ - if (neg && p[0] == opt) { \ - int indx, count = cnt; \ - len -= (count + 2); \ - if (len < 0) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != (count + 2) || \ - citype != opt) \ - break; \ - for (indx = 0; indx < count; ++indx) {\ - GETCHAR(cichar, p); \ - if (cichar != ((u_char *) &val)[indx]) \ - break; \ - }\ - if (indx != count) \ - break; \ - IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \ - neg = 0; \ - } - -#define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val)) -#define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val)) - -#define REJCIVOID(opt, neg) \ - if (neg && p[0] == opt) { \ - if ((len -= CILEN_VOID) < 0) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_VOID || citype != opt) \ - break; \ - IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \ - neg = 0; \ - } - -/* a reject for RIP/SAP is invalid since we don't send it and you can't - reject something which is not sent. (You can NAK, but you can't REJ.) */ -#define REJCIPROTO(opt, neg, val, bit) \ - if (neg && p[0] == opt) { \ - if ((len -= CILEN_PROTOCOL) < 0) \ - break; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_PROTOCOL) \ - break; \ - GETSHORT(cishort, p); \ - if (cishort != to_external (val) || cishort == RIP_SAP) \ - break; \ - IPXCPDEBUG((LOG_INFO, "ipxcp_rejci short opt %d", opt)); \ - neg = 0; \ - } -/* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - try = *go; - - do { - REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network); - REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node); - REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name); - REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0); -/* - * This is the end of the record. - */ - if (len == 0) { - if (f->state != OPENED) - *go = try; - return (1); - } - } while (0); -/* - * The frame is invalid at this point. - */ - IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!")); - return 0; -} - -/* - * ipxcp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - */ -static int -ipxcp_reqci(f, inp, len, reject_if_disagree) - fsm *f; - u_char *inp; /* Requested CIs */ - int *len; /* Length of requested CIs */ - int reject_if_disagree; -{ - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ - u_short cishort; /* Parsed short value */ - u_int32_t cinetwork; /* Parsed address values */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ -/* - * The network number must match. Choose the larger of the two. - */ - case IPX_NETWORK_NUMBER: - IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request")); - - /* if we wont negotiate the network number or the length is wrong - then reject the option */ - if ( !ao->neg_nn || cilen != CILEN_NETN ) { - orc = CONFREJ; - break; - } - GETLONG(cinetwork, p); - IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl)); - - /* If the network numbers match then acknowledge them. */ - if (cinetwork != 0) { - ho->his_network = cinetwork; - ho->neg_nn = 1; - if (wo->our_network == cinetwork) - break; -/* - * If the network number is not given or we don't accept their change or - * the network number is too small then NAK it. - */ - if (! ao->accept_network || cinetwork < wo->our_network) { - DECPTR (sizeof (u_int32_t), p); - PUTLONG (wo->our_network, p); - orc = CONFNAK; - } - break; - } -/* - * The peer sent '0' for the network. Give it ours if we have one. - */ - if (go->our_network != 0) { - DECPTR (sizeof (u_int32_t), p); - PUTLONG (wo->our_network, p); - orc = CONFNAK; -/* - * We don't have one. Reject the value. - */ - } else - orc = CONFREJ; - - break; -/* - * The node number is required - */ - case IPX_NODE_NUMBER: - IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request")); - - /* if we wont negotiate the node number or the length is wrong - then reject the option */ - if ( cilen != CILEN_NODEN ) { - orc = CONFREJ; - break; - } - - copy_node (p, ho->his_node); - ho->neg_node = 1; -/* - * If the remote does not have a number and we do then NAK it with the value - * which we have for it. (We never have a default value of zero.) - */ - if (zero_node (ho->his_node)) { - orc = CONFNAK; - copy_node (wo->his_node, p); - INCPTR (sizeof (wo->his_node), p); - break; - } -/* - * If you have given me the expected network node number then I'll accept - * it now. - */ - if (compare_node (wo->his_node, ho->his_node)) { - orc = CONFACK; - ho->neg_node = 1; - INCPTR (sizeof (wo->his_node), p); - break; - } -/* - * If his node number is the same as ours then ask him to try the next - * value. - */ - if (compare_node (ho->his_node, go->our_node)) { - inc_node (ho->his_node); - orc = CONFNAK; - copy_node (ho->his_node, p); - INCPTR (sizeof (wo->his_node), p); - break; - } -/* - * If we don't accept a new value then NAK it. - */ - if (! ao->accept_remote) { - copy_node (wo->his_node, p); - INCPTR (sizeof (wo->his_node), p); - orc = CONFNAK; - break; - } - orc = CONFACK; - ho->neg_node = 1; - INCPTR (sizeof (wo->his_node), p); - break; -/* - * Compression is not desired at this time. It is always rejected. - */ - case IPX_COMPRESSION_PROTOCOL: - IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request ")); - orc = CONFREJ; - break; -/* - * The routing protocol is a bitmask of various types. Any combination - * of the values RIP_SAP and NLSP are permissible. 'IPX_NONE' for no - * routing protocol must be specified only once. - */ - case IPX_ROUTER_PROTOCOL: - if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) { - orc = CONFREJ; - break; - } - - GETSHORT (cishort, p); - IPXCPDEBUG((LOG_INFO, - "Remote router protocol number 0x%04x", - cishort)); - - if (wo->neg_router == 0) { - wo->neg_router = 1; - wo->router = BIT(IPX_NONE); - } - - if ((cishort == IPX_NONE && ho->router != 0) || - (ho->router & BIT(IPX_NONE))) { - orc = CONFREJ; - break; - } - - cishort = BIT(cishort); - if (ho->router & cishort) { - orc = CONFREJ; - break; - } - - ho->router |= cishort; - ho->neg_router = 1; - - /* Finally do not allow a router protocol which we do not - support. */ - - if ((cishort & (ao->router | BIT(IPX_NONE))) == 0) { - int protocol; - - if (cishort == BIT(NLSP) && - (ao->router & BIT(RIP_SAP)) && - !wo->tried_rip) { - protocol = RIP_SAP; - wo->tried_rip = 1; - } else - protocol = IPX_NONE; - - DECPTR (sizeof (u_int16_t), p); - PUTSHORT (protocol, p); - orc = CONFNAK; - } - break; -/* - * The router name is advisorary. Just accept it if it is not too large. - */ - case IPX_ROUTER_NAME: - IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request")); - if (cilen >= CILEN_NAME) { - int name_size = cilen - CILEN_NAME; - if (name_size > sizeof (ho->name)) - name_size = sizeof (ho->name) - 1; - memset (ho->name, 0, sizeof (ho->name)); - memcpy (ho->name, p, name_size); - ho->name [name_size] = '\0'; - ho->neg_name = 1; - orc = CONFACK; - break; - } - orc = CONFREJ; - break; -/* - * This is advisorary. - */ - case IPX_COMPLETE: - IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request")); - if (cilen != CILEN_COMPLETE) - orc = CONFREJ; - else { - ho->neg_complete = 1; - orc = CONFACK; - } - break; -/* - * All other entries are not known at this time. - */ - default: - IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request")); - orc = CONFREJ; - break; - } - -endswitch: - IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc))); - - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ - orc = CONFREJ; /* Get tough if so */ - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) - BCOPY(cip, ucp, cilen); /* Move it */ - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their address, and they didn't send their address, then we - * send a NAK with an IPX_NODE_NUMBER option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - - if (rc != CONFREJ && !ho->neg_node && - wo->req_nn && !reject_if_disagree) { - if (rc == CONFACK) { - rc = CONFNAK; - wo->req_nn = 0; /* don't ask again */ - ucp = inp; /* reset pointer */ - } - - if (zero_node (wo->his_node)) - inc_node (wo->his_node); - - PUTCHAR (IPX_NODE_NUMBER, ucp); - PUTCHAR (CILEN_NODEN, ucp); - copy_node (wo->his_node, ucp); - INCPTR (sizeof (wo->his_node), ucp); - } - - *len = ucp - inp; /* Compute output length */ - IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc))); - return (rc); /* Return final code */ -} - -/* - * ipxcp_up - IPXCP has come UP. - * - * Configure the IP network interface appropriately and bring it up. - */ - -static void -ipxcp_up(f) - fsm *f; -{ - int unit = f->unit; - - IPXCPDEBUG((LOG_INFO, "ipxcp: up")); - - /* The default router protocol is RIP/SAP. */ - if (ho->router == 0) - ho->router = BIT(RIP_SAP); - - if (go->router == 0) - go->router = BIT(RIP_SAP); - - /* Fetch the network number */ - if (!ho->neg_nn) - ho->his_network = wo->his_network; - - if (!ho->neg_node) - copy_node (wo->his_node, ho->his_node); - - if (!wo->neg_node && !go->neg_node) - copy_node (wo->our_node, go->our_node); - - if (zero_node (go->our_node)) { - static char errmsg[] = "Could not determine local IPX node address"; - IPXCPDEBUG((LOG_ERR, errmsg)); - ipxcp_close(f->unit, errmsg); - return; - } - - go->network = go->our_network; - if (ho->his_network != 0 && ho->his_network > go->network) - go->network = ho->his_network; - - if (go->network == 0) { - static char errmsg[] = "Can not determine network number"; - IPXCPDEBUG((LOG_ERR, errmsg)); - ipxcp_close (unit, errmsg); - return; - } - - /* bring the interface up */ - if (!sifup(unit)) { - IPXCPDEBUG((LOG_WARNING, "sifup failed")); - ipxcp_close(unit, "Interface configuration failed"); - return; - } - - /* set the network number for IPX */ - if (!sipxfaddr(unit, go->network, go->our_node)) { - IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed")); - ipxcp_close(unit, "Interface configuration failed"); - return; - } - - /* - * Execute the ipx-up script, like this: - * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX - */ - - ipxcp_script (f, _PATH_IPXUP); -} - -/* - * ipxcp_down - IPXCP has gone DOWN. - * - * Take the IP network interface down, clear its addresses - * and delete routes through it. - */ - -static void -ipxcp_down(f) - fsm *f; -{ - IPXCPDEBUG((LOG_INFO, "ipxcp: down")); - - cipxfaddr (f->unit); - sifdown(f->unit); - ipxcp_script (f, _PATH_IPXDOWN); -} - - -/* - * ipxcp_script - Execute a script with arguments - * interface-name tty-name speed local-IPX remote-IPX networks. - */ -static void -ipxcp_script(f, script) - fsm *f; - char *script; -{ - char strspeed[32], strlocal[32], strremote[32]; - char strnetwork[32], strpid[32]; - char *argv[14], strproto_lcl[32], strproto_rmt[32]; - - sprintf (strpid, "%d", getpid()); - sprintf (strspeed, "%d", baud_rate); - - strproto_lcl[0] = '\0'; - if (go->neg_router && ((go->router & BIT(IPX_NONE)) == 0)) { - if (go->router & BIT(RIP_SAP)) - strcpy (strproto_lcl, "RIP "); - if (go->router & BIT(NLSP)) - strcat (strproto_lcl, "NLSP "); - } - - if (strproto_lcl[0] == '\0') - strcpy (strproto_lcl, "NONE "); - - strproto_lcl[strlen (strproto_lcl)-1] = '\0'; - - strproto_rmt[0] = '\0'; - if (ho->neg_router && ((ho->router & BIT(IPX_NONE)) == 0)) { - if (ho->router & BIT(RIP_SAP)) - strcpy (strproto_rmt, "RIP "); - if (ho->router & BIT(NLSP)) - strcat (strproto_rmt, "NLSP "); - } - - if (strproto_rmt[0] == '\0') - strcpy (strproto_rmt, "NONE "); - - strproto_rmt[strlen (strproto_rmt)-1] = '\0'; - - strcpy (strnetwork, ipx_ntoa (go->network)); - - sprintf (strlocal, - "%02X%02X%02X%02X%02X%02X", - NODE(go->our_node)); - - sprintf (strremote, - "%02X%02X%02X%02X%02X%02X", - NODE(ho->his_node)); - - argv[0] = script; - argv[1] = ifname; - argv[2] = devnam; - argv[3] = strspeed; - argv[4] = strnetwork; - argv[5] = strlocal; - argv[6] = strremote; - argv[7] = strproto_lcl; - argv[8] = strproto_rmt; - argv[9] = go->name; - argv[10] = ho->name; - argv[11] = ipparam; - argv[12] = strpid; - argv[13] = NULL; - run_program(script, argv, 0); -} - -/* - * ipxcp_printpkt - print the contents of an IPXCP packet. - */ -static char *ipxcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej" -}; - -static int -ipxcp_printpkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer)(void *, char *, ...); - void *arg; -{ - int code, id, len, olen; - u_char *pstart, *optend; - u_short cishort; - u_int32_t cilong; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *)) - printer(arg, " %s", ipxcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < CILEN_VOID || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case IPX_NETWORK_NUMBER: - if (olen == CILEN_NETN) { - p += 2; - GETLONG(cilong, p); - printer (arg, "network %s", ipx_ntoa (cilong)); - } - break; - case IPX_NODE_NUMBER: - if (olen == CILEN_NODEN) { - p += 2; - printer (arg, "node "); - while (p < optend) { - GETCHAR(code, p); - printer(arg, "%.2x", (int) (unsigned int) (unsigned char) code); - } - } - break; - case IPX_COMPRESSION_PROTOCOL: - if (olen == CILEN_COMPRESS) { - p += 2; - GETSHORT (cishort, p); - printer (arg, "compression %d", (int) cishort); - } - break; - case IPX_ROUTER_PROTOCOL: - if (olen == CILEN_PROTOCOL) { - p += 2; - GETSHORT (cishort, p); - printer (arg, "router proto %d", (int) cishort); - } - break; - case IPX_ROUTER_NAME: - if (olen >= CILEN_NAME) { - p += 2; - printer (arg, "router name \""); - while (p < optend) { - GETCHAR(code, p); - if (code >= 0x20 && code <= 0x7E) - printer (arg, "%c", (int) (unsigned int) (unsigned char) code); - else - printer (arg, " \\%.2x", (int) (unsigned int) (unsigned char) code); - } - printer (arg, "\""); - } - break; - case IPX_COMPLETE: - if (olen == CILEN_COMPLETE) { - p += 2; - printer (arg, "complete"); - } - break; - default: - break; - } - - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code); - } - - return p - pstart; -} -#endif /* ifdef IPX_CHANGE */ diff --git a/usr.sbin/pppd/ipxcp.h b/usr.sbin/pppd/ipxcp.h deleted file mode 100644 index 0890181..0000000 --- a/usr.sbin/pppd/ipxcp.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ipxcp.h - IPX Control Protocol definitions. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * Options. - */ -#define IPX_NETWORK_NUMBER 1 /* IPX Network Number */ -#define IPX_NODE_NUMBER 2 -#define IPX_COMPRESSION_PROTOCOL 3 -#define IPX_ROUTER_PROTOCOL 4 -#define IPX_ROUTER_NAME 5 -#define IPX_COMPLETE 6 - -/* Values for the router protocol */ -#define IPX_NONE 0 -#define RIP_SAP 2 -#define NLSP 4 - -typedef struct ipxcp_options { - int neg_node : 1; /* Negotiate IPX node number? */ - int req_node : 1; /* Ask peer to send IPX node number? */ - - int neg_nn : 1; /* Negotiate IPX network number? */ - int req_nn : 1; /* Ask peer to send IPX network number */ - - int neg_name : 1; /* Negotiate IPX router name */ - int neg_complete : 1; /* Negotiate completion */ - int neg_router : 1; /* Negotiate IPX router number */ - - int accept_local : 1; /* accept peer's value for ournode */ - int accept_remote : 1; /* accept peer's value for hisnode */ - int accept_network : 1; /* accept network number */ - - int tried_nlsp : 1; /* I have suggested NLSP already */ - int tried_rip : 1; /* I have suggested RIP/SAP already */ - - u_int32_t his_network; /* base network number */ - u_int32_t our_network; /* our value for network number */ - u_int32_t network; /* the final network number */ - - u_char his_node[6]; /* peer's node number */ - u_char our_node[6]; /* our node number */ - u_char name [48]; /* name of the router */ - int router; /* routing protocol */ -} ipxcp_options; - -extern fsm ipxcp_fsm[]; -extern ipxcp_options ipxcp_wantoptions[]; -extern ipxcp_options ipxcp_gotoptions[]; -extern ipxcp_options ipxcp_allowoptions[]; -extern ipxcp_options ipxcp_hisoptions[]; - -extern struct protent ipxcp_protent; diff --git a/usr.sbin/pppd/lcp.c b/usr.sbin/pppd/lcp.c deleted file mode 100644 index a10a460..0000000 --- a/usr.sbin/pppd/lcp.c +++ /dev/null @@ -1,1859 +0,0 @@ -/* - * lcp.c - PPP Link Control Protocol. - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -/* - * TODO: - */ - -#include <stdio.h> -#include <string.h> -#include <syslog.h> -#include <assert.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <netinet/in.h> - -#include "pppd.h" -#include "fsm.h" -#include "lcp.h" -#include "chap.h" -#include "magic.h" - -/* global vars */ -fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ -lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ -lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ -u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */ - -static u_int32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ -static u_int32_t lcp_echo_number = 0; /* ID number of next echo frame */ -static u_int32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ - -static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void lcp_resetci(fsm *); /* Reset our CI */ -static int lcp_cilen(fsm *); /* Return length of our CI */ -static void lcp_addci(fsm *, u_char *, int *); /* Add our CI to pkt */ -static int lcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */ -static int lcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */ -static int lcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */ -static int lcp_reqci(fsm *, u_char *, int *, int); /* Rcv peer CI */ -static void lcp_up(fsm *); /* We're UP */ -static void lcp_down(fsm *); /* We're DOWN */ -static void lcp_starting(fsm *); /* We need lower layer up */ -static void lcp_finished(fsm *); /* We need lower layer down */ -static int lcp_extcode(fsm *, int, int, u_char *, int); -static void lcp_rprotrej(fsm *, u_char *, int); - -/* - * routines to send LCP echos to peer - */ - -static void lcp_echo_lowerup(int); -static void lcp_echo_lowerdown(int); -static void LcpEchoTimeout(void *); -static void lcp_received_echo_reply(fsm *, int, u_char *, int); -static void LcpSendEchoRequest(fsm *); -static void LcpLinkFailure(fsm *); -static void LcpEchoCheck(fsm *); - -static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ - lcp_resetci, /* Reset our Configuration Information */ - lcp_cilen, /* Length of our Configuration Information */ - lcp_addci, /* Add our Configuration Information */ - lcp_ackci, /* ACK our Configuration Information */ - lcp_nakci, /* NAK our Configuration Information */ - lcp_rejci, /* Reject our Configuration Information */ - lcp_reqci, /* Request peer's Configuration Information */ - lcp_up, /* Called when fsm reaches OPENED state */ - lcp_down, /* Called when fsm leaves OPENED state */ - lcp_starting, /* Called when we want the lower layer up */ - lcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - lcp_extcode, /* Called to handle LCP-specific codes */ - "LCP" /* String name of protocol */ -}; - -/* - * Protocol entry points. - * Some of these are called directly. - */ - -static void lcp_init(int); -static void lcp_input(int, u_char *, int); -static void lcp_protrej(int); -static int lcp_printpkt(u_char *, int, - void (*)(void *, char *, ...), void *); - -struct protent lcp_protent = { - PPP_LCP, - lcp_init, - lcp_input, - lcp_protrej, - lcp_lowerup, - lcp_lowerdown, - lcp_open, - lcp_close, - lcp_printpkt, - NULL, - 1, - "LCP", - NULL, - NULL, - NULL -}; - -int lcp_loopbackfail = DEFLOOPBACKFAIL; - -/* - * Length of each type of configuration option (in octets) - */ -#define CILEN_VOID 2 -#define CILEN_CHAR 3 -#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ -#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ -#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ -#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ -#define CILEN_CBCP 3 - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - - -/* - * lcp_init - Initialize LCP. - */ -static void -lcp_init(unit) - int unit; -{ - fsm *f = &lcp_fsm[unit]; - lcp_options *wo = &lcp_wantoptions[unit]; - lcp_options *ao = &lcp_allowoptions[unit]; - - f->unit = unit; - f->protocol = PPP_LCP; - f->callbacks = &lcp_callbacks; - - fsm_init(f); - - wo->passive = 0; - wo->silent = 0; - wo->restart = 0; /* Set to 1 in kernels or multi-line - implementations */ - wo->neg_mru = 1; - wo->mru = DEFMRU; - wo->neg_asyncmap = 0; - wo->asyncmap = 0; - wo->neg_chap = 0; /* Set to 1 on server */ - wo->neg_upap = 0; /* Set to 1 on server */ - wo->chap_mdtype = CHAP_DIGEST_MD5; - wo->neg_magicnumber = 1; - wo->neg_pcompression = 1; - wo->neg_accompression = 1; - wo->neg_lqr = 0; /* no LQR implementation yet */ - wo->neg_cbcp = 0; - - ao->neg_mru = 1; - ao->mru = MAXMRU; - ao->neg_asyncmap = 1; - ao->asyncmap = 0; - ao->neg_chap = 1; - ao->chap_mdtype = CHAP_DIGEST_MD5; - ao->neg_upap = 1; - ao->neg_magicnumber = 1; - ao->neg_pcompression = 1; - ao->neg_accompression = 1; - ao->neg_lqr = 0; /* no LQR implementation yet */ -#ifdef CBCP_SUPPORT - ao->neg_cbcp = 1; -#else - ao->neg_cbcp = 0; -#endif - - memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); - xmit_accm[unit][3] = 0x60000000; -} - - -/* - * lcp_open - LCP is allowed to come up. - */ -void -lcp_open(unit) - int unit; -{ - fsm *f = &lcp_fsm[unit]; - lcp_options *wo = &lcp_wantoptions[unit]; - - f->flags = 0; - if (wo->passive) - f->flags |= OPT_PASSIVE; - if (wo->silent) - f->flags |= OPT_SILENT; - fsm_open(f); -} - - -/* - * lcp_close - Take LCP down. - */ -void -lcp_close(unit, reason) - int unit; - char *reason; -{ - fsm *f = &lcp_fsm[unit]; - - if (phase != PHASE_DEAD) - phase = PHASE_TERMINATE; - if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { - /* - * This action is not strictly according to the FSM in RFC1548, - * but it does mean that the program terminates if you do a - * lcp_close() in passive/silent mode when a connection hasn't - * been established. - */ - f->state = CLOSED; - lcp_finished(f); - - } else - fsm_close(&lcp_fsm[unit], reason); -} - - -/* - * lcp_lowerup - The lower layer is up. - */ -void -lcp_lowerup(unit) - int unit; -{ - lcp_options *wo = &lcp_wantoptions[unit]; - - /* - * Don't use A/C or protocol compression on transmission, - * but accept A/C and protocol compressed packets - * if we are going to ask for A/C and protocol compression. - */ - ppp_set_xaccm(unit, xmit_accm[unit]); - ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0); - ppp_recv_config(unit, PPP_MRU, 0xffffffff, - wo->neg_pcompression, wo->neg_accompression); - peer_mru[unit] = PPP_MRU; - lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0]; - - fsm_lowerup(&lcp_fsm[unit]); -} - - -/* - * lcp_lowerdown - The lower layer is down. - */ -void -lcp_lowerdown(unit) - int unit; -{ - fsm_lowerdown(&lcp_fsm[unit]); -} - - -/* - * lcp_input - Input LCP packet. - */ -static void -lcp_input(unit, p, len) - int unit; - u_char *p; - int len; -{ - fsm *f = &lcp_fsm[unit]; - - fsm_input(f, p, len); -} - - -/* - * lcp_extcode - Handle a LCP-specific code. - */ -static int -lcp_extcode(f, code, id, inp, len) - fsm *f; - int code, id; - u_char *inp; - int len; -{ - u_char *magp; - - switch( code ){ - case PROTREJ: - lcp_rprotrej(f, inp, len); - break; - - case ECHOREQ: - if (f->state != OPENED) - break; - LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id)); - magp = inp; - PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); - fsm_sdata(f, ECHOREP, id, inp, len); - break; - - case ECHOREP: - lcp_received_echo_reply(f, id, inp, len); - break; - - case DISCREQ: - break; - - default: - return 0; - } - return 1; -} - - -/* - * lcp_rprotrej - Receive a Protocol-Reject. - * - * Figure out which protocol is rejected and inform it. - */ -static void -lcp_rprotrej(f, inp, len) - fsm *f; - u_char *inp; - int len; -{ - int i; - struct protent *protp; - u_short prot; - - LCPDEBUG((LOG_INFO, "lcp_rprotrej.")); - - if (len < sizeof (u_short)) { - LCPDEBUG((LOG_INFO, - "lcp_rprotrej: Rcvd short Protocol-Reject packet!")); - return; - } - - GETSHORT(prot, inp); - - LCPDEBUG((LOG_INFO, - "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!", - prot)); - - /* - * Protocol-Reject packets received in any state other than the LCP - * OPENED state SHOULD be silently discarded. - */ - if( f->state != OPENED ){ - LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d", - f->state)); - return; - } - - /* - * Upcall the proper Protocol-Reject routine. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol == prot && protp->enabled_flag) { - (*protp->protrej)(f->unit); - return; - } - - syslog(LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x", - prot); -} - - -/* - * lcp_protrej - A Protocol-Reject was received. - */ -/*ARGSUSED*/ -static void -lcp_protrej(unit) - int unit; -{ - /* - * Can't reject LCP! - */ - LCPDEBUG((LOG_WARNING, - "lcp_protrej: Received Protocol-Reject for LCP!")); - fsm_protreject(&lcp_fsm[unit]); -} - - -/* - * lcp_sprotrej - Send a Protocol-Reject for some protocol. - */ -void -lcp_sprotrej(unit, p, len) - int unit; - u_char *p; - int len; -{ - /* - * Send back the protocol and the information field of the - * rejected packet. We only get here if LCP is in the OPENED state. - */ - p += 2; - len -= 2; - - fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, - p, len); -} - - -/* - * lcp_resetci - Reset our CI. - */ -static void -lcp_resetci(f) - fsm *f; -{ - lcp_wantoptions[f->unit].magicnumber = magic(); - lcp_wantoptions[f->unit].numloops = 0; - lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; - peer_mru[f->unit] = PPP_MRU; - auth_reset(f->unit); -} - - -/* - * lcp_cilen - Return length of our CI. - */ -static int -lcp_cilen(f) - fsm *f; -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - -#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) -#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) -#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) -#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) -#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) -#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) - /* - * NB: we only ask for one of CHAP and UPAP, even if we will - * accept either. - */ - return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) + - LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + - LENCICHAP(go->neg_chap) + - LENCISHORT(!go->neg_chap && go->neg_upap) + - LENCILQR(go->neg_lqr) + - LENCICBCP(go->neg_cbcp) + - LENCILONG(go->neg_magicnumber) + - LENCIVOID(go->neg_pcompression) + - LENCIVOID(go->neg_accompression)); -} - - -/* - * lcp_addci - Add our desired CIs to a packet. - */ -static void -lcp_addci(f, ucp, lenp) - fsm *f; - u_char *ucp; - int *lenp; -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - u_char *start_ucp = ucp; - -#define ADDCIVOID(opt, neg) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_VOID, ucp); \ - } -#define ADDCISHORT(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_SHORT, ucp); \ - PUTSHORT(val, ucp); \ - } -#define ADDCICHAP(opt, neg, val, digest) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAP, ucp); \ - PUTSHORT(val, ucp); \ - PUTCHAR(digest, ucp); \ - } -#define ADDCILONG(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LONG, ucp); \ - PUTLONG(val, ucp); \ - } -#define ADDCILQR(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LQR, ucp); \ - PUTSHORT(PPP_LQR, ucp); \ - PUTLONG(val, ucp); \ - } -#define ADDCICHAR(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAR, ucp); \ - PUTCHAR(val, ucp); \ - } - - ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru); - ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, - go->asyncmap); - ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); - ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); - ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); - ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); - - if (ucp - start_ucp != *lenp) { - /* this should never happen, because peer_mtu should be 1500 */ - syslog(LOG_ERR, "Bug in lcp_addci: wrong length"); - } -} - - -/* - * lcp_ackci - Ack our CIs. - * This should not modify any state if the Ack is bad. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int -lcp_ackci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - u_char cilen, citype, cichar; - u_short cishort; - u_int32_t cilong; - - /* - * CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define ACKCIVOID(opt, neg) \ - if (neg) { \ - if ((len -= CILEN_VOID) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_VOID || \ - citype != opt) \ - goto bad; \ - } -#define ACKCISHORT(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_SHORT) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_SHORT || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - } -#define ACKCICHAR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_CHAR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAR || \ - citype != opt) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != val) \ - goto bad; \ - } -#define ACKCICHAP(opt, neg, val, digest) \ - if (neg) { \ - if ((len -= CILEN_CHAP) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAP || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != digest) \ - goto bad; \ - } -#define ACKCILONG(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LONG) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LONG || \ - citype != opt) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } -#define ACKCILQR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LQR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LQR || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != PPP_LQR) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } - - ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru); - ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, - go->asyncmap); - ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); - ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); - ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); - ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); -bad: - LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!")); - return (0); -} - - -/* - * lcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if LCP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int -lcp_nakci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - lcp_options *wo = &lcp_wantoptions[f->unit]; - u_char citype, cichar, *next; - u_short cishort; - u_int32_t cilong; - lcp_options no; /* options we've seen Naks for */ - lcp_options try; /* options to request next time */ - int looped_back = 0; - int cilen; - - BZERO(&no, sizeof(no)); - try = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIVOID(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - no.neg = 1; \ - code \ - } -#define NAKCICHAP(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#define NAKCICHAR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAR && \ - p[1] == CILEN_CHAR && \ - p[0] == opt) { \ - len -= CILEN_CHAR; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#define NAKCISHORT(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#define NAKCILONG(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } -#define NAKCILQR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } - - /* - * We don't care if they want to send us smaller packets than - * we want. Therefore, accept any MRU less than what we asked for, - * but then ignore the new value when setting the MRU in the kernel. - * If they send us a bigger MRU than what we asked, accept it, up to - * the limit of the default MRU we'd get if we didn't negotiate. - */ - if (go->neg_mru && go->mru != DEFMRU) { - NAKCISHORT(CI_MRU, neg_mru, - if (cishort <= wo->mru || cishort <= DEFMRU) - try.mru = cishort; - ); - } - - /* - * Add any characters they want to our (receive-side) asyncmap. - */ - if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) { - NAKCILONG(CI_ASYNCMAP, neg_asyncmap, - try.asyncmap = go->asyncmap | cilong; - ); - } - - /* - * If they've nak'd our authentication-protocol, check whether - * they are proposing a different protocol, or a different - * hash algorithm for CHAP. - */ - if ((go->neg_chap || go->neg_upap) - && len >= CILEN_SHORT - && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { - cilen = p[1]; - len -= cilen; - no.neg_chap = go->neg_chap; - no.neg_upap = go->neg_upap; - INCPTR(2, p); - GETSHORT(cishort, p); - if (cishort == PPP_PAP && cilen == CILEN_SHORT) { - /* - * If we were asking for CHAP, they obviously don't want to do it. - * If we weren't asking for CHAP, then we were asking for PAP, - * in which case this Nak is bad. - */ - if (!go->neg_chap) - goto bad; - try.neg_chap = 0; - - } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { - GETCHAR(cichar, p); - if (go->neg_chap) { - /* - * We were asking for CHAP/MD5; they must want a different - * algorithm. If they can't do MD5, we'll have to stop - * asking for CHAP. - */ - if (cichar != go->chap_mdtype) - try.neg_chap = 0; - } else { - /* - * Stop asking for PAP if we were asking for it. - */ - try.neg_upap = 0; - } - - } else { - /* - * We don't recognize what they're suggesting. - * Stop asking for what we were asking for. - */ - if (go->neg_chap) - try.neg_chap = 0; - else - try.neg_upap = 0; - p += cilen - CILEN_SHORT; - } - } - - /* - * If they can't cope with our link quality protocol, we'll have - * to stop asking for LQR. We haven't got any other protocol. - * If they Nak the reporting period, take their value XXX ? - */ - NAKCILQR(CI_QUALITY, neg_lqr, - if (cishort != PPP_LQR) - try.neg_lqr = 0; - else - try.lqr_period = cilong; - ); - - /* - * Only implementing CBCP...not the rest of the callback options - */ - NAKCICHAR(CI_CALLBACK, neg_cbcp, - try.neg_cbcp = 0; - ); - - /* - * Check for a looped-back line. - */ - NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, - try.magicnumber = magic(); - looped_back = 1; - ); - - /* - * Peer shouldn't send Nak for protocol compression or - * address/control compression requests; they should send - * a Reject instead. If they send a Nak, treat it as a Reject. - */ - NAKCIVOID(CI_PCOMPRESSION, neg_pcompression, - try.neg_pcompression = 0; - ); - NAKCIVOID(CI_ACCOMPRESSION, neg_accompression, - try.neg_accompression = 0; - ); - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If we see an option that we requested, or one we've already seen - * in this packet, then this packet is bad. - * If we wanted to respond by starting to negotiate on the requested - * option(s), we could, but we don't, because except for the - * authentication type and quality protocol, if we are not negotiating - * an option, it is because we were told not to. - * For the authentication type, the Nak from the peer means - * `let me authenticate myself with you' which is a bit pointless. - * For the quality protocol, the Nak means `ask me to send you quality - * reports', but if we didn't ask for them, we don't want them. - * An option we don't recognize represents the peer asking to - * negotiate some option we don't support, so ignore it. - */ - while (len > CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if (cilen < CILEN_VOID || (len -= cilen) < 0) - goto bad; - next = p + cilen - 2; - - switch (citype) { - case CI_MRU: - if ((go->neg_mru && go->mru != DEFMRU) - || no.neg_mru || cilen != CILEN_SHORT) - goto bad; - GETSHORT(cishort, p); - if (cishort < DEFMRU) - try.mru = cishort; - break; - case CI_ASYNCMAP: - if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) - || no.neg_asyncmap || cilen != CILEN_LONG) - goto bad; - break; - case CI_AUTHTYPE: - if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap) - goto bad; - break; - case CI_MAGICNUMBER: - if (go->neg_magicnumber || no.neg_magicnumber || - cilen != CILEN_LONG) - goto bad; - break; - case CI_PCOMPRESSION: - if (go->neg_pcompression || no.neg_pcompression - || cilen != CILEN_VOID) - goto bad; - break; - case CI_ACCOMPRESSION: - if (go->neg_accompression || no.neg_accompression - || cilen != CILEN_VOID) - goto bad; - break; - case CI_QUALITY: - if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) - goto bad; - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) - goto bad; - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != OPENED) { - if (looped_back) { - if (++try.numloops >= lcp_loopbackfail) { - syslog(LOG_NOTICE, "Serial line is looped back."); - lcp_close(f->unit, "Loopback detected"); - } - } else - try.numloops = 0; - *go = try; - } - - return 1; - -bad: - LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!")); - return 0; -} - - -/* - * lcp_rejci - Peer has Rejected some of our CIs. - * This should not modify any state if the Reject is bad - * or if LCP is in the OPENED state. - * - * Returns: - * 0 - Reject was bad. - * 1 - Reject was good. - */ -static int -lcp_rejci(f, p, len) - fsm *f; - u_char *p; - int len; -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - u_char cichar; - u_short cishort; - u_int32_t cilong; - lcp_options try; /* options to request next time */ - - try = *go; - - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIVOID(opt, neg) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - try.neg = 0; \ - LCPDEBUG((LOG_INFO, "lcp_rejci rejected void opt %d", opt)); \ - } -#define REJCISHORT(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci rejected short opt %d", opt)); \ - } -#define REJCICHAP(opt, neg, val, digest) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if (cishort != val || cichar != digest) \ - goto bad; \ - try.neg = 0; \ - try.neg_upap = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \ - } -#define REJCILONG(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cilong != val) \ - goto bad; \ - try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci rejected long opt %d", opt)); \ - } -#define REJCILQR(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cishort != PPP_LQR || cilong != val) \ - goto bad; \ - try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \ - } -#define REJCICBCP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CBCP && \ - p[1] == CILEN_CBCP && \ - p[0] == opt) { \ - len -= CILEN_CBCP; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if (cichar != val) \ - goto bad; \ - try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci rejected Callback opt %d", opt)); \ - } - - REJCISHORT(CI_MRU, neg_mru, go->mru); - REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); - REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); - if (!go->neg_chap) { - REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); - } - REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); - REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); - REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); - REJCIVOID(CI_PCOMPRESSION, neg_pcompression); - REJCIVOID(CI_ACCOMPRESSION, neg_accompression); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != OPENED) - *go = try; - return 1; - -bad: - LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!")); - return 0; -} - - -/* - * lcp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - */ -static int -lcp_reqci(f, inp, lenp, reject_if_disagree) - fsm *f; - u_char *inp; /* Requested CIs */ - int *lenp; /* Length of requested CIs */ - int reject_if_disagree; -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - lcp_options *ho = &lcp_hisoptions[f->unit]; - lcp_options *ao = &lcp_allowoptions[f->unit]; - u_char *cip, *next; /* Pointer to current and next CIs */ - int cilen, citype, cichar; /* Parsed len, type, char value */ - u_short cishort; /* Parsed short value */ - u_int32_t cilong; /* Parse long value */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *rejp; /* Pointer to next char in reject frame */ - u_char *nakp; /* Pointer to next char in Nak frame */ - int l = *lenp; /* Length left */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - nakp = nak_buffer; - rejp = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - citype = 0; - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_MRU: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MRU")); - if (!ao->neg_mru || /* Allow option? */ - cilen != CILEN_SHORT) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETSHORT(cishort, p); /* Parse MRU */ - LCPDEBUG((LOG_INFO, "(%d)", cishort)); - - /* - * He must be able to receive at least our minimum. - * No need to check a maximum. If he sends a large number, - * we'll just ignore it. - */ - if (cishort < MINMRU) { - orc = CONFNAK; /* Nak CI */ - PUTCHAR(CI_MRU, nakp); - PUTCHAR(CILEN_SHORT, nakp); - PUTSHORT(MINMRU, nakp); /* Give him a hint */ - break; - } - ho->neg_mru = 1; /* Remember he sent MRU */ - ho->mru = cishort; /* And remember value */ - break; - - case CI_ASYNCMAP: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ASYNCMAP")); - if (!ao->neg_asyncmap || - cilen != CILEN_LONG) { - orc = CONFREJ; - break; - } - GETLONG(cilong, p); - LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong)); - - /* - * Asyncmap must have set at least the bits - * which are set in lcp_allowoptions[unit].asyncmap. - */ - if ((ao->asyncmap & ~cilong) != 0) { - orc = CONFNAK; - PUTCHAR(CI_ASYNCMAP, nakp); - PUTCHAR(CILEN_LONG, nakp); - PUTLONG(ao->asyncmap | cilong, nakp); - break; - } - ho->neg_asyncmap = 1; - ho->asyncmap = cilong; - break; - - case CI_AUTHTYPE: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE")); - if (cilen < CILEN_SHORT || - !(ao->neg_upap || ao->neg_chap)) { - /* - * Reject the option if we're not willing to authenticate. - */ - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - LCPDEBUG((LOG_INFO, "(%x)", cishort)); - - /* - * Authtype must be UPAP or CHAP. - * - * Note: if both ao->neg_upap and ao->neg_chap are set, - * and the peer sends a Configure-Request with two - * authenticate-protocol requests, one for CHAP and one - * for UPAP, then we will reject the second request. - * Whether we end up doing CHAP or UPAP depends then on - * the ordering of the CIs in the peer's Configure-Request. - */ - - if (cishort == PPP_PAP) { - if (ho->neg_chap || /* we've already accepted CHAP */ - cilen != CILEN_SHORT) { - LCPDEBUG((LOG_WARNING, - "lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_upap) { /* we don't want to do PAP */ - orc = CONFNAK; /* NAK it and suggest CHAP */ - PUTCHAR(CI_AUTHTYPE, nakp); - PUTCHAR(CILEN_CHAP, nakp); - PUTSHORT(PPP_CHAP, nakp); - PUTCHAR(ao->chap_mdtype, nakp); - break; - } - ho->neg_upap = 1; - break; - } - if (cishort == PPP_CHAP) { - if (ho->neg_upap || /* we've already accepted PAP */ - cilen != CILEN_CHAP) { - LCPDEBUG((LOG_INFO, - "lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_chap) { /* we don't want to do CHAP */ - orc = CONFNAK; /* NAK it and suggest PAP */ - PUTCHAR(CI_AUTHTYPE, nakp); - PUTCHAR(CILEN_SHORT, nakp); - PUTSHORT(PPP_PAP, nakp); - break; - } - GETCHAR(cichar, p); /* get digest type*/ - if (cichar != CHAP_DIGEST_MD5 -#ifdef CHAPMS - && cichar != CHAP_MICROSOFT -#endif - ) { - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakp); - PUTCHAR(CILEN_CHAP, nakp); - PUTSHORT(PPP_CHAP, nakp); - PUTCHAR(ao->chap_mdtype, nakp); - break; - } - ho->chap_mdtype = cichar; /* save md type */ - ho->neg_chap = 1; - break; - } - - /* - * We don't recognize the protocol they're asking for. - * Nak it with something we're willing to do. - * (At this point we know ao->neg_upap || ao->neg_chap.) - */ - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakp); - if (ao->neg_chap) { - PUTCHAR(CILEN_CHAP, nakp); - PUTSHORT(PPP_CHAP, nakp); - PUTCHAR(ao->chap_mdtype, nakp); - } else { - PUTCHAR(CILEN_SHORT, nakp); - PUTSHORT(PPP_PAP, nakp); - } - break; - - case CI_QUALITY: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY")); - if (!ao->neg_lqr || - cilen != CILEN_LQR) { - orc = CONFREJ; - break; - } - - GETSHORT(cishort, p); - GETLONG(cilong, p); - LCPDEBUG((LOG_INFO, "(%x %x)", cishort, (unsigned int) cilong)); - - /* - * Check the protocol and the reporting period. - * XXX When should we Nak this, and what with? - */ - if (cishort != PPP_LQR) { - orc = CONFNAK; - PUTCHAR(CI_QUALITY, nakp); - PUTCHAR(CILEN_LQR, nakp); - PUTSHORT(PPP_LQR, nakp); - PUTLONG(ao->lqr_period, nakp); - break; - } - break; - - case CI_MAGICNUMBER: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MAGICNUMBER")); - if (!(ao->neg_magicnumber || go->neg_magicnumber) || - cilen != CILEN_LONG) { - orc = CONFREJ; - break; - } - GETLONG(cilong, p); - LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong)); - - /* - * He must have a different magic number. - */ - if (go->neg_magicnumber && - cilong == go->magicnumber) { - cilong = magic(); /* Don't put magic() inside macro! */ - orc = CONFNAK; - PUTCHAR(CI_MAGICNUMBER, nakp); - PUTCHAR(CILEN_LONG, nakp); - PUTLONG(cilong, nakp); - break; - } - ho->neg_magicnumber = 1; - ho->magicnumber = cilong; - break; - - - case CI_PCOMPRESSION: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION")); - if (!ao->neg_pcompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_pcompression = 1; - break; - - case CI_ACCOMPRESSION: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION")); - if (!ao->neg_accompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_accompression = 1; - break; - - default: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d", - citype)); - orc = CONFREJ; - break; - } - -endswitch: - LCPDEBUG((LOG_INFO, " (%s)", CODENAME(orc))); - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree /* Getting fed up with sending NAKs? */ - && citype != CI_MAGICNUMBER) { - orc = CONFREJ; /* Get tough if so */ - } else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - rc = CONFNAK; - } - } - if (orc == CONFREJ) { /* Reject this CI */ - rc = CONFREJ; - if (cip != rejp) /* Need to move rejected CI? */ - BCOPY(cip, rejp, cilen); /* Move it */ - INCPTR(cilen, rejp); /* Update output pointer */ - } - } - - /* - * If we wanted to send additional NAKs (for unsent CIs), the - * code would go here. The extra NAKs would go at *nakp. - * At present there are no cases where we want to ask the - * peer to negotiate an option. - */ - - switch (rc) { - case CONFACK: - *lenp = next - inp; - break; - case CONFNAK: - /* - * Copy the Nak'd options from the nak_buffer to the caller's buffer. - */ - *lenp = nakp - nak_buffer; - BCOPY(nak_buffer, inp, *lenp); - break; - case CONFREJ: - *lenp = rejp - inp; - break; - } - - LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -/* - * lcp_up - LCP has come UP. - */ -static void -lcp_up(f) - fsm *f; -{ - lcp_options *wo = &lcp_wantoptions[f->unit]; - lcp_options *ho = &lcp_hisoptions[f->unit]; - lcp_options *go = &lcp_gotoptions[f->unit]; - lcp_options *ao = &lcp_allowoptions[f->unit]; - - if (!go->neg_magicnumber) - go->magicnumber = 0; - if (!ho->neg_magicnumber) - ho->magicnumber = 0; - - /* - * Set our MTU to the smaller of the MTU we wanted and - * the MRU our peer wanted. If we negotiated an MRU, - * set our MRU to the larger of value we wanted and - * the value we got in the negotiation. - */ - ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), - (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), - ho->neg_pcompression, ho->neg_accompression); - ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU), - (go->neg_asyncmap? go->asyncmap: 0xffffffff), - go->neg_pcompression, go->neg_accompression); - - if (ho->neg_mru) - peer_mru[f->unit] = ho->mru; - - lcp_echo_lowerup(f->unit); /* Enable echo messages */ - - link_established(f->unit); -} - - -/* - * lcp_down - LCP has gone DOWN. - * - * Alert other protocols. - */ -static void -lcp_down(f) - fsm *f; -{ - lcp_options *go = &lcp_gotoptions[f->unit]; - - lcp_echo_lowerdown(f->unit); - - link_down(f->unit); - - ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0); - ppp_recv_config(f->unit, PPP_MRU, - (go->neg_asyncmap? go->asyncmap: 0xffffffff), - go->neg_pcompression, go->neg_accompression); - peer_mru[f->unit] = PPP_MRU; -} - - -/* - * lcp_starting - LCP needs the lower layer up. - */ -static void -lcp_starting(f) - fsm *f; -{ - link_required(f->unit); -} - - -/* - * lcp_finished - LCP has finished with the lower layer. - */ -static void -lcp_finished(f) - fsm *f; -{ - link_terminated(f->unit); -} - - -/* - * lcp_printpkt - print the contents of an LCP packet. - */ -static char *lcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej", "ProtRej", - "EchoReq", "EchoRep", "DiscReq" -}; - -static int -lcp_printpkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer)(void *, char *, ...); - void *arg; -{ - int code, id, len, olen; - u_char *pstart, *optend; - u_short cishort; - u_int32_t cilong; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) - printer(arg, " %s", lcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_MRU: - if (olen == CILEN_SHORT) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "mru %d", cishort); - } - break; - case CI_ASYNCMAP: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "asyncmap 0x%x", cilong); - } - break; - case CI_AUTHTYPE: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "auth "); - GETSHORT(cishort, p); - switch (cishort) { - case PPP_PAP: - printer(arg, "pap"); - break; - case PPP_CHAP: - printer(arg, "chap"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_QUALITY: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "quality "); - GETSHORT(cishort, p); - switch (cishort) { - case PPP_LQR: - printer(arg, "lqr"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_CALLBACK: - if (olen >= CILEN_CHAR) { - p += 2; - printer(arg, "callback "); - GETSHORT(cishort, p); - switch (cishort) { - case CBCP_OPT: - printer(arg, "CBCP"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_MAGICNUMBER: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "magic 0x%x", cilong); - } - break; - case CI_PCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "pcomp"); - } - break; - case CI_ACCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "accomp"); - } - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - - case ECHOREQ: - case ECHOREP: - case DISCREQ: - if (len >= 4) { - GETLONG(cilong, p); - printer(arg, " magic=0x%x", cilong); - p += 4; - len -= 4; - } - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} - -/* - * Time to shut down the link because there is nothing out there. - */ - -static -void LcpLinkFailure (f) - fsm *f; -{ - if (f->state == OPENED) { - syslog(LOG_INFO, "No response to %d echo-requests", lcp_echos_pending); - syslog(LOG_NOTICE, "Serial link appears to be disconnected."); - lcp_close(f->unit, "Peer not responding"); - } -} - -/* - * Timer expired for the LCP echo requests from this process. - */ - -static void -LcpEchoCheck (f) - fsm *f; -{ - LcpSendEchoRequest (f); - if (f->state != OPENED) - return; - - /* - * Start the timer for the next interval. - */ - assert (lcp_echo_timer_running==0); - TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); - lcp_echo_timer_running = 1; -} - -/* - * LcpEchoTimeout - Timer expired on the LCP echo - */ - -static void -LcpEchoTimeout (arg) - void *arg; -{ - if (lcp_echo_timer_running != 0) { - lcp_echo_timer_running = 0; - LcpEchoCheck ((fsm *) arg); - } -} - -/* - * LcpEchoReply - LCP has received a reply to the echo - */ - -static void -lcp_received_echo_reply (f, id, inp, len) - fsm *f; - int id; u_char *inp; int len; -{ - u_int32_t magic; - - /* Check the magic number - don't count replies from ourselves. */ - if (len < 4) { - syslog(LOG_DEBUG, "lcp: received short Echo-Reply, length %d", len); - return; - } - GETLONG(magic, inp); - if (lcp_gotoptions[f->unit].neg_magicnumber - && magic == lcp_gotoptions[f->unit].magicnumber) { - syslog(LOG_WARNING, "appear to have received our own echo-reply!"); - return; - } - - /* Reset the number of outstanding echo frames */ - lcp_echos_pending = 0; -} - -/* - * LcpSendEchoRequest - Send an echo request frame to the peer - */ - -static void -LcpSendEchoRequest (f) - fsm *f; -{ - u_int32_t lcp_magic; - u_char pkt[4], *pktp; - - /* - * Detect the failure of the peer at this point. - */ - if (lcp_echo_fails != 0) { - if (lcp_echos_pending >= lcp_echo_fails) { - LcpLinkFailure(f); - lcp_echos_pending = 0; - } - } - - /* - * Make and send the echo request frame. - */ - if (f->state == OPENED) { - lcp_magic = lcp_gotoptions[f->unit].magicnumber; - pktp = pkt; - PUTLONG(lcp_magic, pktp); - fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt); - ++lcp_echos_pending; - } -} - -/* - * lcp_echo_lowerup - Start the timer for the LCP frame - */ - -static void -lcp_echo_lowerup (unit) - int unit; -{ - fsm *f = &lcp_fsm[unit]; - - /* Clear the parameters for generating echo frames */ - lcp_echos_pending = 0; - lcp_echo_number = 0; - lcp_echo_timer_running = 0; - - /* If a timeout interval is specified then start the timer */ - if (lcp_echo_interval != 0) - LcpEchoCheck (f); -} - -/* - * lcp_echo_lowerdown - Stop the timer for the LCP frame - */ - -static void -lcp_echo_lowerdown (unit) - int unit; -{ - fsm *f = &lcp_fsm[unit]; - - if (lcp_echo_timer_running != 0) { - UNTIMEOUT (LcpEchoTimeout, f); - lcp_echo_timer_running = 0; - } -} diff --git a/usr.sbin/pppd/lcp.h b/usr.sbin/pppd/lcp.h deleted file mode 100644 index 603a32f..0000000 --- a/usr.sbin/pppd/lcp.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * lcp.h - Link Control Protocol definitions. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * Options. - */ -#define CI_MRU 1 /* Maximum Receive Unit */ -#define CI_ASYNCMAP 2 /* Async Control Character Map */ -#define CI_AUTHTYPE 3 /* Authentication Type */ -#define CI_QUALITY 4 /* Quality Protocol */ -#define CI_MAGICNUMBER 5 /* Magic Number */ -#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ -#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ -#define CI_CALLBACK 13 /* callback */ - -/* - * LCP-specific packet types. - */ -#define PROTREJ 8 /* Protocol Reject */ -#define ECHOREQ 9 /* Echo Request */ -#define ECHOREP 10 /* Echo Reply */ -#define DISCREQ 11 /* Discard Request */ -#define CBCP_OPT 6 /* Use callback control protocol */ - -/* - * The state of options is described by an lcp_options structure. - */ -typedef struct lcp_options { - int passive : 1; /* Don't die if we don't get a response */ - int silent : 1; /* Wait for the other end to start first */ - int restart : 1; /* Restart vs. exit after close */ - int neg_mru : 1; /* Negotiate the MRU? */ - int neg_asyncmap : 1; /* Negotiate the async map? */ - int neg_upap : 1; /* Ask for UPAP authentication? */ - int neg_chap : 1; /* Ask for CHAP authentication? */ - int neg_magicnumber : 1; /* Ask for magic number? */ - int neg_pcompression : 1; /* HDLC Protocol Field Compression? */ - int neg_accompression : 1; /* HDLC Address/Control Field Compression? */ - int neg_lqr : 1; /* Negotiate use of Link Quality Reports */ - int neg_cbcp : 1; /* Negotiate use of CBCP */ - u_short mru; /* Value of MRU */ - u_char chap_mdtype; /* which MD type (hashing algorithm) */ - u_int32_t asyncmap; /* Value of async map */ - u_int32_t magicnumber; - int numloops; /* Number of loops during magic number neg. */ - u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */ -} lcp_options; - -extern fsm lcp_fsm[]; -extern lcp_options lcp_wantoptions[]; -extern lcp_options lcp_gotoptions[]; -extern lcp_options lcp_allowoptions[]; -extern lcp_options lcp_hisoptions[]; -extern u_int32_t xmit_accm[][8]; - -#define DEFMRU 1500 /* Try for this */ -#define MINMRU 128 /* No MRUs below this */ -#define MAXMRU 16384 /* Normally limit MRU to this */ - -void lcp_open(int); -void lcp_close(int, char *); -void lcp_lowerup(int); -void lcp_lowerdown(int); -void lcp_sprotrej(int, u_char *, int); /* send protocol reject */ - -extern struct protent lcp_protent; - -/* Default number of times we receive our magic number from the peer - before deciding the link is looped-back. */ -#define DEFLOOPBACKFAIL 10 diff --git a/usr.sbin/pppd/magic.c b/usr.sbin/pppd/magic.c deleted file mode 100644 index b4627b1..0000000 --- a/usr.sbin/pppd/magic.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * magic.c - PPP Magic Number routines. - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#include <stdio.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/time.h> - -#include "pppd.h" -#include "magic.h" - -extern long mrand48(void); -extern void srand48(long); - -/* - * magic_init - Initialize the magic number generator. - * - * Attempts to compute a random number seed which will not repeat. - * The current method uses the current hostid, current process ID - * and current time, currently. - */ -void -magic_init() -{ - long seed; - struct timeval t; - - gettimeofday(&t, NULL); - seed = get_host_seed() ^ t.tv_sec ^ t.tv_usec ^ getpid(); - srand48(seed); -} - -/* - * magic - Returns the next magic number. - */ -u_int32_t -magic() -{ - return (u_int32_t) mrand48(); -} - -#ifdef NO_DRAND48 -/* - * Substitute procedures for those systems which don't have - * drand48 et al. - */ - -double -drand48() -{ - return (double)random() / (double)0x7fffffffL; /* 2**31-1 */ -} - -long -mrand48() -{ - return random(); -} - -void -srand48(seedval) -long seedval; -{ - srandom((int)seedval); -} - -#endif diff --git a/usr.sbin/pppd/magic.h b/usr.sbin/pppd/magic.h deleted file mode 100644 index c574131..0000000 --- a/usr.sbin/pppd/magic.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * magic.h - PPP Magic Number definitions. - * - * 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. - * - * $FreeBSD$ - */ - -void magic_init(void); /* Initialize the magic number generator */ -u_int32_t magic(void); /* Returns the next magic number */ diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c deleted file mode 100644 index 7850726..0000000 --- a/usr.sbin/pppd/main.c +++ /dev/null @@ -1,1723 +0,0 @@ -/* - * main.c - Point-to-Point Protocol main module - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#include <stdio.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> -#include <errno.h> -#include <fcntl.h> -#include <syslog.h> -#include <netdb.h> -#include <utmp.h> -#include <pwd.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <sys/socket.h> - -#include "pppd.h" -#include "magic.h" -#include "fsm.h" -#include "lcp.h" -#include "ipcp.h" -#ifdef INET6 -#include "ipv6cp.h" -#endif -#include "upap.h" -#include "chap.h" -#include "ccp.h" -#include "pathnames.h" -#include "patchlevel.h" - -#ifdef CBCP_SUPPORT -#include "cbcp.h" -#endif - -#if defined(SUNOS4) -extern char *strerror(); -#endif - -#ifdef IPX_CHANGE -#include "ipxcp.h" -#endif /* IPX_CHANGE */ -#ifdef AT_CHANGE -#include "atcp.h" -#endif - -/* interface vars */ -char ifname[32]; /* Interface name */ -int ifunit; /* Interface unit number */ - -char *progname; /* Name of this program */ -char hostname[MAXNAMELEN]; /* Our hostname */ -static char pidfilename[MAXPATHLEN]; /* name of pid file */ -static char iffilename[MAXPATHLEN]; /* name of if file */ -static char default_devnam[MAXPATHLEN]; /* name of default device */ -static pid_t pid; /* Our pid */ -static uid_t uid; /* Our real user-id */ -time_t etime,stime; /* End and Start time */ -int minutes; /* connection duration */ -static int conn_running; /* we have a [dis]connector running */ - -int ttyfd = -1; /* Serial port file descriptor */ -mode_t tty_mode = -1; /* Original access permissions to tty */ -int baud_rate; /* Actual bits/second for serial device */ -int hungup; /* terminal has been hung up */ -int privileged; /* we're running as real uid root */ -int need_holdoff; /* need holdoff period before restarting */ -int detached; /* have detached from terminal */ - -int phase; /* where the link is at */ -int kill_link; -int open_ccp_flag; - -char **script_env; /* Env. variable values for scripts */ -int s_env_nalloc; /* # words avail at script_env */ - -u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */ -u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ - -static int n_children; /* # child processes still running */ - -static int locked; /* lock() has succeeded */ - -char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n"; - -/* Prototypes for procedures local to this file. */ - -static void create_pidfile(void); -static void cleanup(void); -static void close_tty(void); -static void get_input(void); -static void calltimeout(void); -static struct timeval *timeleft(struct timeval *); -static void kill_my_pg(int); -static void hup(int); -static void term(int); -static void chld(int); -static void toggle_debug(int); -static void open_ccp(int); -static void bad_signal(int); -static void holdoff_end(void *); -static int device_script(char *, int, int); -static void reap_kids(void); -static void pr_log(void *, char *, ...); - -extern char *ttyname(int); -extern char *getlogin(void); -int main(int, char *[]); - -#ifdef ultrix -#undef O_NONBLOCK -#define O_NONBLOCK O_NDELAY -#endif - -#ifdef ULTRIX -#define setlogmask(x) -#endif - -/* - * PPP Data Link Layer "protocol" table. - * One entry per supported protocol. - * The last entry must be NULL. - */ -struct protent *protocols[] = { - &lcp_protent, - &pap_protent, - &chap_protent, -#ifdef CBCP_SUPPORT - &cbcp_protent, -#endif - &ipcp_protent, -#ifdef INET6 - &ipv6cp_protent, -#endif - &ccp_protent, -#ifdef IPX_CHANGE - &ipxcp_protent, -#endif -#ifdef AT_CHANGE - &atcp_protent, -#endif - NULL -}; - -int -main(argc, argv) - int argc; - char *argv[]; -{ - int i, n, fdflags; - struct sigaction sa; - FILE *iffile; - char *p; - struct passwd *pw; - struct timeval timo; - sigset_t mask; - struct protent *protp; - struct stat statbuf; - int connect_attempts = 0; - char numbuf[16]; - - phase = PHASE_INITIALIZE; - p = ttyname(0); - if (p) - strcpy(devnam, p); - strcpy(default_devnam, devnam); - - script_env = NULL; - - /* Initialize syslog facilities */ -#ifdef ULTRIX - openlog("pppd", LOG_PID); -#else - openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); - setlogmask(LOG_UPTO(LOG_INFO)); -#endif - - if (gethostname(hostname, MAXNAMELEN) < 0 ) { - option_error("Couldn't get hostname: %m"); - die(1); - } - hostname[MAXNAMELEN-1] = 0; - - uid = getuid(); - privileged = uid == 0; - sprintf(numbuf, "%d", uid); - script_setenv("UID", numbuf); - - /* - * Initialize to the standard option set, then parse, in order, - * the system options file, the user's options file, - * the tty's options file, and the command line arguments. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - (*protp->init)(0); - - progname = *argv; - - if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1) - || !options_from_user()) - exit(1); - scan_args(argc-1, argv+1); /* look for tty name on command line */ - if (!options_for_tty() - || !parse_args(argc-1, argv+1)) - exit(1); - - /* - * Check that we are running as root. - */ - if (geteuid() != 0) { - option_error("must be root to run %s, since it is not setuid-root", - argv[0]); - die(1); - } - - if (!ppp_available()) { - option_error(no_ppp_msg); - exit(1); - } - - /* - * Check that the options given are valid and consistent. - */ - sys_check_options(); - auth_check_options(); - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->check_options != NULL) - (*protp->check_options)(); - if (demand && connector == 0) { - option_error("connect script required for demand-dialling\n"); - exit(1); - } - - script_setenv("DEVICE", devnam); - sprintf(numbuf, "%d", baud_rate); - script_setenv("SPEED", numbuf); - - /* - * If the user has specified the default device name explicitly, - * pretend they hadn't. - */ - if (!default_device && strcmp(devnam, default_devnam) == 0) - default_device = 1; - if (default_device) - nodetach = 1; - - /* - * Initialize system-dependent stuff and magic number package. - */ - sys_init(); - magic_init(); - if (debug) - setlogmask(LOG_UPTO(LOG_DEBUG)); - - /* - * Detach ourselves from the terminal, if required, - * and identify who is running us. - */ - if (nodetach == 0) - detach(); - pid = getpid(); - p = getlogin(); - stime = time((time_t *) NULL); - if (p == NULL) { - pw = getpwuid(uid); - if (pw != NULL && pw->pw_name != NULL) - p = pw->pw_name; - else - p = "(unknown)"; - } - syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d", - VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid); - - /* - * Compute mask of all interesting signals and install signal handlers - * for each. Only one signal handler may be active at a time. Therefore, - * all other signals should be masked when any handler is executing. - */ - sigemptyset(&mask); - sigaddset(&mask, SIGHUP); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGTERM); - sigaddset(&mask, SIGCHLD); - -#define SIGNAL(s, handler) { \ - sa.sa_handler = handler; \ - if (sigaction(s, &sa, NULL) < 0) { \ - syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \ - die(1); \ - } \ - } - - sa.sa_mask = mask; - sa.sa_flags = 0; - SIGNAL(SIGHUP, hup); /* Hangup */ - SIGNAL(SIGINT, term); /* Interrupt */ - SIGNAL(SIGTERM, term); /* Terminate */ - SIGNAL(SIGCHLD, chld); - - SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */ - SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */ - - /* - * Install a handler for other signals which would otherwise - * cause pppd to exit without cleaning up. - */ - SIGNAL(SIGABRT, bad_signal); - SIGNAL(SIGALRM, bad_signal); - SIGNAL(SIGFPE, bad_signal); - SIGNAL(SIGILL, bad_signal); - SIGNAL(SIGPIPE, bad_signal); - SIGNAL(SIGQUIT, bad_signal); - SIGNAL(SIGSEGV, bad_signal); -#ifdef SIGBUS - SIGNAL(SIGBUS, bad_signal); -#endif -#ifdef SIGEMT - SIGNAL(SIGEMT, bad_signal); -#endif -#ifdef SIGPOLL - SIGNAL(SIGPOLL, bad_signal); -#endif -#ifdef SIGPROF - SIGNAL(SIGPROF, bad_signal); -#endif -#ifdef SIGSYS - SIGNAL(SIGSYS, bad_signal); -#endif -#ifdef SIGTRAP - SIGNAL(SIGTRAP, bad_signal); -#endif -#ifdef SIGVTALRM - SIGNAL(SIGVTALRM, bad_signal); -#endif -#ifdef SIGXCPU - SIGNAL(SIGXCPU, bad_signal); -#endif -#ifdef SIGXFSZ - SIGNAL(SIGXFSZ, bad_signal); -#endif - - /* - * Apparently we can get a SIGPIPE when we call syslog, if - * syslogd has died and been restarted. Ignoring it seems - * be sufficient. - */ - signal(SIGPIPE, SIG_IGN); - - /* - * If we're doing dial-on-demand, set up the interface now. - */ - if (demand) { - /* - * Open the loopback channel and set it up to be the ppp interface. - */ - open_ppp_loopback(); - - syslog(LOG_INFO, "Using interface ppp%d", ifunit); - (void) sprintf(ifname, "ppp%d", ifunit); - script_setenv("IFNAME", ifname); - - create_pidfile(); /* write pid to file */ - - /* - * Configure the interface and mark it up, etc. - */ - demand_conf(); - } - - for (;;) { - - need_holdoff = 1; - - if (demand) { - /* - * Don't do anything until we see some activity. - */ - phase = PHASE_DORMANT; - kill_link = 0; - demand_unblock(); - for (;;) { - wait_loop_output(timeleft(&timo)); - calltimeout(); - if (kill_link) { - if (!persist) - die(0); - kill_link = 0; - } - if (get_loop_output()) - break; - reap_kids(); - } - - /* - * Now we want to bring up the link. - */ - demand_block(); - syslog(LOG_INFO, "Starting link"); - } - - /* - * Lock the device if we've been asked to. - */ - if (lockflag && !default_device) { - if (lock(devnam) < 0) - goto fail; - locked = 1; - } - - /* - * Open the serial device and set it up to be the ppp interface. - * First we open it in non-blocking mode so we can set the - * various termios flags appropriately. If we aren't dialling - * out and we want to use the modem lines, we reopen it later - * in order to wait for the carrier detect signal from the modem. - */ - while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) { - if (errno != EINTR) - syslog(LOG_ERR, "Failed to open %s: %m", devnam); - if (!persist || errno != EINTR) - goto fail; - } - if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 - || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) - syslog(LOG_WARNING, - "Couldn't reset non-blocking mode on device: %m"); - - hungup = 0; - kill_link = 0; - - /* - * Do the equivalent of `mesg n' to stop broadcast messages. - */ - if (fstat(ttyfd, &statbuf) < 0 - || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) { - syslog(LOG_WARNING, - "Couldn't restrict write permissions to %s: %m", devnam); - } else - tty_mode = statbuf.st_mode; - - /* run connection script */ - if (connector && connector[0]) { - MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); - - /* - * Set line speed, flow control, etc. - * On most systems we set CLOCAL for now so that we can talk - * to the modem before carrier comes up. But this has the - * side effect that we might miss it if CD drops before we - * get to clear CLOCAL below. On systems where we can talk - * successfully to the modem with CLOCAL clear and CD down, - * we can clear CLOCAL at this point. - */ - set_up_tty(ttyfd, 1); - - /* drop dtr to hang up in case modem is off hook */ - if (!default_device && modem) { - setdtr(ttyfd, FALSE); - sleep(1); - setdtr(ttyfd, TRUE); - } - - if (device_script(connector, ttyfd, ttyfd) < 0) { - syslog(LOG_ERR, "Connect script failed"); - setdtr(ttyfd, FALSE); - connect_attempts++; - goto fail; - } - - - syslog(LOG_INFO, "Serial connection established."); - sleep(1); /* give it time to set up its terminal */ - } - - connect_attempts = 0; /* we made it through ok */ - - /* set line speed, flow control, etc.; clear CLOCAL if modem option */ - set_up_tty(ttyfd, 0); - - /* reopen tty if necessary to wait for carrier */ - if (connector == NULL && modem) { - while ((i = open(devnam, O_RDWR)) < 0) { - if (errno != EINTR) - syslog(LOG_ERR, "Failed to reopen %s: %m", devnam); - if (!persist || errno != EINTR || - hungup || kill_link) - goto fail; - } - close(i); - } - - /* run welcome script, if any */ - if (welcomer && welcomer[0]) { - if (device_script(welcomer, ttyfd, ttyfd) < 0) - syslog(LOG_WARNING, "Welcome script failed"); - } - - /* set up the serial device as a ppp interface */ - establish_ppp(ttyfd); - - if (!demand) { - - syslog(LOG_INFO, "Using interface ppp%d", ifunit); - (void) sprintf(ifname, "ppp%d", ifunit); - - create_pidfile(); /* write pid to file */ - - /* write interface unit number to file */ - for (n = strlen(devnam); n > 0 ; n--) - if (devnam[n] == '/') { - n++; - break; - } - (void) sprintf(iffilename, "%s%s.if", _PATH_VARRUN, &devnam[n]); - if ((iffile = fopen(iffilename, "w")) != NULL) { - fprintf(iffile, "ppp%d\n", ifunit); - (void) fclose(iffile); - } else { - syslog(LOG_ERR, "Failed to create if file %s: %m", iffilename); - iffilename[0] = 0; - } - - script_setenv("IFNAME", ifname); - } - - /* - * Start opening the connection and wait for - * incoming events (reply, timeout, etc.). - */ - syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); - stime = time((time_t *) NULL); - lcp_lowerup(0); - lcp_open(0); /* Start protocol */ - for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) { - wait_input(timeleft(&timo)); - calltimeout(); - get_input(); - if (kill_link) { - lcp_close(0, "User request"); - kill_link = 0; - } - if (open_ccp_flag) { - if (phase == PHASE_NETWORK) { - ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ - (*ccp_protent.open)(0); - } - open_ccp_flag = 0; - } - reap_kids(); /* Don't leave dead kids lying around */ - } - - /* - * If we may want to bring the link up again, transfer - * the ppp unit back to the loopback. Set the - * real serial device back to its normal mode of operation. - */ - clean_check(); - if (demand) - restore_loop(); - disestablish_ppp(ttyfd); - - /* - * Run disconnector script, if requested. - * XXX we may not be able to do this if the line has hung up! - */ - if (disconnector && !hungup) { - set_up_tty(ttyfd, 1); - if (device_script(disconnector, ttyfd, ttyfd) < 0) { - syslog(LOG_WARNING, "disconnect script failed"); - } else { - syslog(LOG_INFO, "Serial link disconnected."); - } - } - - fail: - if (ttyfd >= 0) - close_tty(); - if (locked) { - unlock(); - locked = 0; - } - - if (!demand) { - if (pidfilename[0] != 0 - && unlink(pidfilename) < 0 && errno != ENOENT) - syslog(LOG_WARNING, "unable to delete pid file: %m"); - pidfilename[0] = 0; - - if (iffile) - if (unlink(iffilename) < 0 && errno != ENOENT) - syslog(LOG_WARNING, "unable to delete if file: %m"); - iffilename[0] = 0; - } - - /* limit to retries? */ - if (max_con_attempts) - if (connect_attempts >= max_con_attempts) - break; - - if (!persist) - die(1); - - if (demand) - demand_discard(); - if (holdoff > 0 && need_holdoff) { - phase = PHASE_HOLDOFF; - TIMEOUT(holdoff_end, NULL, holdoff); - do { - wait_time(timeleft(&timo)); - calltimeout(); - if (kill_link) { - if (!persist) - die(0); - kill_link = 0; - phase = PHASE_DORMANT; /* allow signal to end holdoff */ - } - reap_kids(); - } while (phase == PHASE_HOLDOFF); - } - } - - die(0); - return 0; -} - -/* - * detach - detach us from the controlling terminal. - */ -void -detach() -{ - if (detached) - return; - if (daemon(0, 0) < 0) { - perror("Couldn't detach from controlling terminal"); - die(1); - } - detached = 1; - pid = getpid(); - /* update pid file if it has been written already */ - if (pidfilename[0]) - create_pidfile(); -} - -/* - * Create a file containing our process ID. - */ -static void -create_pidfile() -{ - FILE *pidfile; - - (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); - if ((pidfile = fopen(pidfilename, "w")) != NULL) { - fprintf(pidfile, "%d\n", pid); - (void) fclose(pidfile); - } else { - syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename); - pidfilename[0] = 0; - } -} - -/* - * holdoff_end - called via a timeout when the holdoff period ends. - */ -static void -holdoff_end(arg) - void *arg; -{ - phase = PHASE_DORMANT; -} - -/* - * get_input - called when incoming data is available. - */ -static void -get_input() -{ - int len, i; - u_char *p; - u_short protocol; - struct protent *protp; - - p = inpacket_buf; /* point to beginning of packet buffer */ - - len = read_packet(inpacket_buf); - if (len < 0) - return; - - if (len == 0) { - etime = time((time_t *) NULL); - minutes = (etime-stime)/60; - syslog(LOG_NOTICE, "Modem hangup, connected for %d minutes", (minutes >1) ? minutes : 1); - hungup = 1; - lcp_lowerdown(0); /* serial link is no longer available */ - link_terminated(0); - return; - } - - if (debug /*&& (debugflags & DBG_INPACKET)*/) - log_packet(p, len, "rcvd ", LOG_DEBUG); - - if (len < PPP_HDRLEN) { - MAINDEBUG((LOG_INFO, "io(): Received short packet.")); - return; - } - - p += 2; /* Skip address and control */ - GETSHORT(protocol, p); - len -= PPP_HDRLEN; - - /* - * Toss all non-LCP packets unless LCP is OPEN. - */ - if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) { - MAINDEBUG((LOG_INFO, - "get_input: Received non-LCP packet when LCP not open.")); - return; - } - - /* - * Until we get past the authentication phase, toss all packets - * except LCP, LQR and authentication packets. - */ - if (phase <= PHASE_AUTHENTICATE - && !(protocol == PPP_LCP || protocol == PPP_LQR - || protocol == PPP_PAP || protocol == PPP_CHAP)) { - MAINDEBUG((LOG_INFO, "get_input: discarding proto 0x%x in phase %d", - protocol, phase)); - return; - } - - /* - * Upcall the proper protocol input routine. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol == protocol && protp->enabled_flag) { - (*protp->input)(0, p, len); - return; - } - if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag - && protp->datainput != NULL) { - (*protp->datainput)(0, p, len); - return; - } - } - - if (debug) - syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol); - lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); -} - - -/* - * quit - Clean up state and exit (with an error indication). - */ -void -quit() -{ - die(1); -} - -/* - * die - like quit, except we can specify an exit status. - */ -void -die(status) - int status; -{ - cleanup(); - syslog(LOG_INFO, "Exit."); - exit(status); -} - -/* - * cleanup - restore anything which needs to be restored before we exit - */ -/* ARGSUSED */ -static void -cleanup() -{ - sys_cleanup(); - - if (ttyfd >= 0) - close_tty(); - - if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) - syslog(LOG_WARNING, "unable to delete pid file: %m"); - pidfilename[0] = 0; - - if (locked) - unlock(); -} - -/* - * close_tty - restore the terminal device and close it. - */ -static void -close_tty() -{ - disestablish_ppp(ttyfd); - - /* drop dtr to hang up */ - if (modem) { - setdtr(ttyfd, FALSE); - /* - * This sleep is in case the serial port has CLOCAL set by default, - * and consequently will reassert DTR when we close the device. - */ - sleep(1); - } - - restore_tty(ttyfd); - - if (tty_mode != (mode_t) -1) - fchmod(ttyfd, tty_mode); - - close(ttyfd); - ttyfd = -1; -} - - -struct callout { - struct timeval c_time; /* time at which to call routine */ - void *c_arg; /* argument to routine */ - void (*c_func)(void *); /* routine */ - struct callout *c_next; -}; - -static struct callout *callout = NULL; /* Callout list */ -static struct timeval timenow; /* Current time */ - -/* - * timeout - Schedule a timeout. - * - * Note that this timeout takes the number of seconds, NOT hz (as in - * the kernel). - */ -void -timeout(func, arg, time) - void (*func)(void *); - void *arg; - int time; -{ - struct callout *newp, *p, **pp; - - MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.", - (long) func, (long) arg, time)); - - /* - * Allocate timeout. - */ - if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) { - syslog(LOG_ERR, "Out of memory in timeout()!"); - die(1); - } - newp->c_arg = arg; - newp->c_func = func; - gettimeofday(&timenow, NULL); - newp->c_time.tv_sec = timenow.tv_sec + time; - newp->c_time.tv_usec = timenow.tv_usec; - - /* - * Find correct place and link it in. - */ - for (pp = &callout; (p = *pp); pp = &p->c_next) - if (newp->c_time.tv_sec < p->c_time.tv_sec - || (newp->c_time.tv_sec == p->c_time.tv_sec - && newp->c_time.tv_usec < p->c_time.tv_sec)) - break; - newp->c_next = p; - *pp = newp; -} - - -/* - * untimeout - Unschedule a timeout. - */ -void -untimeout(func, arg) - void (*func)(void *); - void *arg; -{ - struct callout **copp, *freep; - - MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); - - /* - * Find first matching timeout and remove it from the list. - */ - for (copp = &callout; (freep = *copp); copp = &freep->c_next) - if (freep->c_func == func && freep->c_arg == arg) { - *copp = freep->c_next; - (void) free((char *) freep); - break; - } -} - - -/* - * calltimeout - Call any timeout routines which are now due. - */ -static void -calltimeout() -{ - struct callout *p; - - while (callout != NULL) { - p = callout; - - if (gettimeofday(&timenow, NULL) < 0) { - syslog(LOG_ERR, "Failed to get time of day: %m"); - die(1); - } - if (!(p->c_time.tv_sec < timenow.tv_sec - || (p->c_time.tv_sec == timenow.tv_sec - && p->c_time.tv_usec <= timenow.tv_usec))) - break; /* no, it's not time yet */ - - callout = p->c_next; - (*p->c_func)(p->c_arg); - - free((char *) p); - } -} - - -/* - * timeleft - return the length of time until the next timeout is due. - */ -static struct timeval * -timeleft(tvp) - struct timeval *tvp; -{ - if (callout == NULL) - return NULL; - - gettimeofday(&timenow, NULL); - tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec; - tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec; - if (tvp->tv_usec < 0) { - tvp->tv_usec += 1000000; - tvp->tv_sec -= 1; - } - if (tvp->tv_sec < 0) - tvp->tv_sec = tvp->tv_usec = 0; - - return tvp; -} - - -/* - * kill_my_pg - send a signal to our process group, and ignore it ourselves. - */ -static void -kill_my_pg(sig) - int sig; -{ - struct sigaction act, oldact; - - act.sa_handler = SIG_IGN; - act.sa_flags = 0; - kill(0, sig); - sigaction(sig, &act, &oldact); - sigaction(sig, &oldact, NULL); -} - - -/* - * hup - Catch SIGHUP signal. - * - * Indicates that the physical layer has been disconnected. - * We don't rely on this indication; if the user has sent this - * signal, we just take the link down. - */ -static void -hup(sig) - int sig; -{ - syslog(LOG_INFO, "Hangup (SIGHUP)"); - kill_link = 1; - if (conn_running) - /* Send the signal to the [dis]connector process(es) also */ - kill_my_pg(sig); -} - - -/* - * term - Catch SIGTERM signal and SIGINT signal (^C/del). - * - * Indicates that we should initiate a graceful disconnect and exit. - */ -/*ARGSUSED*/ -static void -term(sig) - int sig; -{ - syslog(LOG_INFO, "Terminating on signal %d.", sig); - persist = 0; /* don't try to restart */ - kill_link = 1; - if (conn_running) - /* Send the signal to the [dis]connector process(es) also */ - kill_my_pg(sig); -} - - -/* - * chld - Catch SIGCHLD signal. - * Calls reap_kids to get status for any dead kids. - */ -static void -chld(sig) - int sig; -{ - reap_kids(); -} - - -/* - * toggle_debug - Catch SIGUSR1 signal. - * - * Toggle debug flag. - */ -/*ARGSUSED*/ -static void -toggle_debug(sig) - int sig; -{ - debug = !debug; - if (debug) { - setlogmask(LOG_UPTO(LOG_DEBUG)); - } else { - setlogmask(LOG_UPTO(LOG_WARNING)); - } -} - - -/* - * open_ccp - Catch SIGUSR2 signal. - * - * Try to (re)negotiate compression. - */ -/*ARGSUSED*/ -static void -open_ccp(sig) - int sig; -{ - open_ccp_flag = 1; -} - - -/* - * bad_signal - We've caught a fatal signal. Clean up state and exit. - */ -static void -bad_signal(sig) - int sig; -{ - static int crashed = 0; - - if (crashed) - _exit(127); - crashed = 1; - syslog(LOG_ERR, "Fatal signal %d", sig); - if (conn_running) - kill_my_pg(SIGTERM); - die(1); -} - - -/* - * device_script - run a program to connect or disconnect the - * serial device. - */ -static int -device_script(program, in, out) - char *program; - int in, out; -{ - int pid; - int status; - int errfd; - - conn_running = 1; - pid = fork(); - - if (pid < 0) { - conn_running = 0; - syslog(LOG_ERR, "Failed to create child process: %m"); - die(1); - } - - if (pid == 0) { - sys_close(); - closelog(); - if (in == out) { - if (in != 0) { - dup2(in, 0); - close(in); - } - dup2(0, 1); - } else { - if (out == 0) - out = dup(out); - if (in != 0) { - dup2(in, 0); - close(in); - } - if (out != 1) { - dup2(out, 1); - close(out); - } - } - if (nodetach == 0) { - close(2); - errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600); - if (errfd >= 0 && errfd != 2) { - dup2(errfd, 2); - close(errfd); - } - } - setuid(getuid()); - setgid(getgid()); - execl("/bin/sh", "sh", "-c", program, (char *)0); - syslog(LOG_ERR, "could not exec /bin/sh: %m"); - _exit(99); - /* NOTREACHED */ - } - - while (waitpid(pid, &status, 0) < 0) { - if (errno == EINTR) - continue; - syslog(LOG_ERR, "error waiting for (dis)connection process: %m"); - die(1); - } - conn_running = 0; - - return (status == 0 ? 0 : -1); -} - - -/* - * run-program - execute a program with given arguments, - * but don't wait for it. - * If the program can't be executed, logs an error unless - * must_exist is 0 and the program file doesn't exist. - */ -int -run_program(prog, args, must_exist) - char *prog; - char **args; - int must_exist; -{ - int pid; - - pid = fork(); - if (pid == -1) { - syslog(LOG_ERR, "Failed to create child process for %s: %m", prog); - return -1; - } - if (pid == 0) { - int new_fd; - - /* Leave the current location */ - (void) setsid(); /* No controlling tty. */ - (void) umask (S_IRWXG|S_IRWXO); - (void) chdir ("/"); /* no current directory. */ - setuid(geteuid()); - setgid(getegid()); - - /* Ensure that nothing of our device environment is inherited. */ - sys_close(); - closelog(); - close (0); - close (1); - close (2); - close (ttyfd); /* tty interface to the ppp device */ - - /* Don't pass handles to the PPP device, even by accident. */ - new_fd = open (_PATH_DEVNULL, O_RDWR); - if (new_fd >= 0) { - if (new_fd != 0) { - dup2 (new_fd, 0); /* stdin <- /dev/null */ - close (new_fd); - } - dup2 (0, 1); /* stdout -> /dev/null */ - dup2 (0, 2); /* stderr -> /dev/null */ - } - -#ifdef BSD - /* Force the priority back to zero if pppd is running higher. */ - if (setpriority (PRIO_PROCESS, 0, 0) < 0) - syslog (LOG_WARNING, "can't reset priority to 0: %m"); -#endif - - /* SysV recommends a second fork at this point. */ - - /* run the program; give it a null environment */ - execve(prog, args, script_env); - if (must_exist || errno != ENOENT) - syslog(LOG_WARNING, "Can't execute %s: %m", prog); - _exit(-1); - } - MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid)); - ++n_children; - return 0; -} - - -/* - * reap_kids - get status from any dead child processes, - * and log a message for abnormal terminations. - */ -static void -reap_kids() -{ - int pid, status; - - if (n_children == 0) - return; - if ((pid = waitpid(-1, &status, WNOHANG)) == -1) { - if (errno != ECHILD) - syslog(LOG_ERR, "Error waiting for child process: %m"); - return; - } - if (pid > 0) { - --n_children; - if (WIFSIGNALED(status)) { - syslog(LOG_WARNING, "Child process %d terminated with signal %d", - pid, WTERMSIG(status)); - } - } -} - - -/* - * log_packet - format a packet and log it. - */ - -char line[256]; /* line to be logged accumulated here */ -char *linep; - -void -log_packet(p, len, prefix, level) - u_char *p; - int len; - char *prefix; - int level; -{ - strcpy(line, prefix); - linep = line + strlen(line); - format_packet(p, len, pr_log, NULL); - if (linep != line) - syslog(level, "%s", line); -} - -/* - * format_packet - make a readable representation of a packet, - * calling `printer(arg, format, ...)' to output it. - */ -void -format_packet(p, len, printer, arg) - u_char *p; - int len; - void (*printer)(void *, char *, ...); - void *arg; -{ - int i, n; - u_short proto; - u_char x; - struct protent *protp; - - if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { - p += 2; - GETSHORT(proto, p); - len -= PPP_HDRLEN; - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (proto == protp->protocol) - break; - if (protp != NULL) { - printer(arg, "[%s", protp->name); - n = (*protp->printpkt)(p, len, printer, arg); - printer(arg, "]"); - p += n; - len -= n; - } else { - printer(arg, "[proto=0x%x]", proto); - } - } - - for (; len > 0; --len) { - GETCHAR(x, p); - printer(arg, " %.2x", x); - } -} - -static void -pr_log __V((void *arg, char *fmt, ...)) -{ - int n; - va_list pvar; - char buf[256]; - -#if __STDC__ - va_start(pvar, fmt); -#else - void *arg; - char *fmt; - va_start(pvar); - arg = va_arg(pvar, void *); - fmt = va_arg(pvar, char *); -#endif - - n = vfmtmsg(buf, sizeof(buf), fmt, pvar); - va_end(pvar); - - if (linep + n + 1 > line + sizeof(line)) { - syslog(LOG_DEBUG, "%s", line); - linep = line; - } - strcpy(linep, buf); - linep += n; -} - -/* - * print_string - print a readable representation of a string using - * printer. - */ -void -print_string(p, len, printer, arg) - char *p; - int len; - void (*printer)(void *, char *, ...); - void *arg; -{ - int c; - - printer(arg, "\""); - for (; len > 0; --len) { - c = *p++; - if (' ' <= c && c <= '~') { - if (c == '\\' || c == '"') - printer(arg, "\\"); - printer(arg, "%c", c); - } else { - switch (c) { - case '\n': - printer(arg, "\\n"); - break; - case '\r': - printer(arg, "\\r"); - break; - case '\t': - printer(arg, "\\t"); - break; - default: - printer(arg, "\\%.3o", c); - } - } - } - printer(arg, "\""); -} - -/* - * novm - log an error message saying we ran out of memory, and die. - */ -void -novm(msg) - char *msg; -{ - syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg); - die(1); -} - -/* - * fmtmsg - format a message into a buffer. Like sprintf except we - * also specify the length of the output buffer, and we handle - * %r (recursive format), %m (error message) and %I (IP address) formats. - * Doesn't do floating-point formats. - * Returns the number of chars put into buf. - */ -int -fmtmsg __V((char *buf, int buflen, char *fmt, ...)) -{ - va_list args; - int n; - -#if __STDC__ - va_start(args, fmt); -#else - char *buf; - int buflen; - char *fmt; - va_start(args); - buf = va_arg(args, char *); - buflen = va_arg(args, int); - fmt = va_arg(args, char *); -#endif - n = vfmtmsg(buf, buflen, fmt, args); - va_end(args); - return n; -} - -/* - * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args. - */ -#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) - -int -vfmtmsg(buf, buflen, fmt, args) - char *buf; - int buflen; - char *fmt; - va_list args; -{ - int c, i, n; - int width, prec, fillch; - int base, len, neg, quoted; - unsigned long val = 0; - char *str, *f, *buf0; - unsigned char *p; - char num[32]; - time_t t; - static char hexchars[] = "0123456789abcdef"; - - buf0 = buf; - --buflen; - while (buflen > 0) { - for (f = fmt; *f != '%' && *f != 0; ++f) - ; - if (f > fmt) { - len = f - fmt; - if (len > buflen) - len = buflen; - memcpy(buf, fmt, len); - buf += len; - buflen -= len; - fmt = f; - } - if (*fmt == 0) - break; - c = *++fmt; - width = prec = 0; - fillch = ' '; - if (c == '0') { - fillch = '0'; - c = *++fmt; - } - if (c == '*') { - width = va_arg(args, int); - c = *++fmt; - } else { - while (isdigit(c)) { - width = width * 10 + c - '0'; - c = *++fmt; - } - } - if (c == '.') { - c = *++fmt; - if (c == '*') { - prec = va_arg(args, int); - c = *++fmt; - } else { - while (isdigit(c)) { - prec = prec * 10 + c - '0'; - c = *++fmt; - } - } - } - str = 0; - base = 0; - neg = 0; - ++fmt; - switch (c) { - case 'd': - i = va_arg(args, int); - if (i < 0) { - neg = 1; - val = -i; - } else - val = i; - base = 10; - break; - case 'o': - val = va_arg(args, unsigned int); - base = 8; - break; - case 'x': - val = va_arg(args, unsigned int); - base = 16; - break; - case 'p': - val = (unsigned long) va_arg(args, void *); - base = 16; - neg = 2; - break; - case 's': - str = va_arg(args, char *); - break; - case 'c': - num[0] = va_arg(args, int); - num[1] = 0; - str = num; - break; - case 'm': - str = strerror(errno); - break; - case 'I': - str = ip_ntoa(va_arg(args, u_int32_t)); - break; - case 'r': - f = va_arg(args, char *); -#if !defined(__powerpc__) && !defined(__amd64__) - n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list)); -#else - /* On the powerpc, a va_list is an array of 1 structure */ - n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *)); -#endif - buf += n; - buflen -= n; - continue; - case 't': - time(&t); - str = ctime(&t); - str += 4; /* chop off the day name */ - str[15] = 0; /* chop off year and newline */ - break; - case 'v': /* "visible" string */ - case 'q': /* quoted string */ - quoted = c == 'q'; - p = va_arg(args, unsigned char *); - if (fillch == '0' && prec > 0) { - n = prec; - } else { - n = strlen((char *)p); - if (prec > 0 && prec < n) - n = prec; - } - while (n > 0 && buflen > 0) { - c = *p++; - --n; - if (!quoted && c >= 0x80) { - OUTCHAR('M'); - OUTCHAR('-'); - c -= 0x80; - } - if (quoted && (c == '"' || c == '\\')) - OUTCHAR('\\'); - if (c < 0x20 || (0x7f <= c && c < 0xa0)) { - if (quoted) { - OUTCHAR('\\'); - switch (c) { - case '\t': OUTCHAR('t'); break; - case '\n': OUTCHAR('n'); break; - case '\b': OUTCHAR('b'); break; - case '\f': OUTCHAR('f'); break; - default: - OUTCHAR('x'); - OUTCHAR(hexchars[c >> 4]); - OUTCHAR(hexchars[c & 0xf]); - } - } else { - if (c == '\t') - OUTCHAR(c); - else { - OUTCHAR('^'); - OUTCHAR(c ^ 0x40); - } - } - } else - OUTCHAR(c); - } - continue; - default: - *buf++ = '%'; - if (c != '%') - --fmt; /* so %z outputs %z etc. */ - --buflen; - continue; - } - if (base != 0) { - str = num + sizeof(num); - *--str = 0; - while (str > num + neg) { - *--str = hexchars[val % base]; - val = val / base; - if (--prec <= 0 && val == 0) - break; - } - switch (neg) { - case 1: - *--str = '-'; - break; - case 2: - *--str = 'x'; - *--str = '0'; - break; - } - len = num + sizeof(num) - 1 - str; - } else { - len = strlen(str); - if (prec > 0 && len > prec) - len = prec; - } - if (width > 0) { - if (width > buflen) - width = buflen; - if ((n = width - len) > 0) { - buflen -= n; - for (; n > 0; --n) - *buf++ = fillch; - } - } - if (len > buflen) - len = buflen; - memcpy(buf, str, len); - buf += len; - buflen -= len; - } - *buf = 0; - return buf - buf0; -} - -/* - * script_setenv - set an environment variable value to be used - * for scripts that we run (e.g. ip-up, auth-up, etc.) - */ -void -script_setenv(var, value) - char *var, *value; -{ - int vl = strlen(var); - int i; - char *p, *newstring; - - newstring = (char *) malloc(vl + strlen(value) + 2); - if (newstring == 0) - return; - strcpy(newstring, var); - newstring[vl] = '='; - strcpy(newstring+vl+1, value); - - /* check if this variable is already set */ - if (script_env != 0) { - for (i = 0; (p = script_env[i]) != 0; ++i) { - if (strncmp(p, var, vl) == 0 && p[vl] == '=') { - free(p); - script_env[i] = newstring; - return; - } - } - } else { - i = 0; - script_env = (char **) malloc(16 * sizeof(char *)); - if (script_env == 0) - return; - s_env_nalloc = 16; - } - - /* reallocate script_env with more space if needed */ - if (i + 1 >= s_env_nalloc) { - int new_n = i + 17; - char **newenv = (char **) realloc((void *)script_env, - new_n * sizeof(char *)); - if (newenv == 0) - return; - script_env = newenv; - s_env_nalloc = new_n; - } - - script_env[i] = newstring; - script_env[i+1] = 0; -} - -/* - * script_unsetenv - remove a variable from the environment - * for scripts. - */ -void -script_unsetenv(var) - char *var; -{ - int vl = strlen(var); - int i; - char *p; - - if (script_env == 0) - return; - for (i = 0; (p = script_env[i]) != 0; ++i) { - if (strncmp(p, var, vl) == 0 && p[vl] == '=') { - free(p); - while ((script_env[i] = script_env[i+1]) != 0) - ++i; - break; - } - } -} diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c deleted file mode 100644 index fa3cf93..0000000 --- a/usr.sbin/pppd/options.c +++ /dev/null @@ -1,2683 +0,0 @@ -/* - * options.c - handles option processing for PPP. - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -#include <ctype.h> -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <limits.h> -#include <stdlib.h> -#include <termios.h> -#include <syslog.h> -#include <string.h> -#include <netdb.h> -#include <paths.h> -#include <pwd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef PPP_FILTER -#include <pcap.h> -#include <pcap-int.h> /* XXX: To get struct pcap */ -#endif - -#include "pppd.h" -#include "pathnames.h" -#include "patchlevel.h" -#include "fsm.h" -#include "lcp.h" -#include "ipcp.h" -#include "upap.h" -#include "chap.h" -#include "ccp.h" -#ifdef CBCP_SUPPORT -#include "cbcp.h" -#endif - -#ifdef INET6 -#include "ipv6cp.h" -#endif - -#ifdef IPX_CHANGE -#include "ipxcp.h" -#endif /* IPX_CHANGE */ - -#include <net/ppp_comp.h> - -#define FALSE 0 -#define TRUE 1 - -#if defined(ultrix) || defined(NeXT) -char *strdup(char *); -#endif - -#ifndef GIDSET_TYPE -#define GIDSET_TYPE gid_t -#endif - -/* - * Option variables and default values. - */ -#ifdef PPP_FILTER -int dflag = 0; /* Tell libpcap we want debugging */ -#endif -int debug = 0; /* Debug flag */ -int kdebugflag = 0; /* Tell kernel to print debug messages */ -int default_device = 1; /* Using /dev/tty or equivalent */ -char devnam[MAXPATHLEN] = _PATH_TTY; /* Device name */ -int crtscts = 0; /* Use hardware flow control */ -int modem = 1; /* Use modem control lines */ -int inspeed = 0; /* Input/Output speed requested */ -u_int32_t netmask = 0; /* IP netmask to set on interface */ -int lockflag = 0; /* Create lock file to lock the serial dev */ -int nodetach = 0; /* Don't detach from controlling tty */ -char *connector = NULL; /* Script to establish physical link */ -char *disconnector = NULL; /* Script to disestablish physical link */ -char *welcomer = NULL; /* Script to run after phys link estab. */ -int max_con_attempts = 0; /* Maximum connect tries in non-demand mode */ -int maxconnect = 0; /* Maximum connect time */ -char user[MAXNAMELEN]; /* Username for PAP */ -char passwd[MAXSECRETLEN]; /* Password for PAP */ -int auth_required = 0; /* Peer is required to authenticate */ -int defaultroute = 0; /* assign default route through interface */ -int proxyarp = 0; /* Set up proxy ARP entry for peer */ -int persist = 0; /* Reopen link after it goes down */ -int uselogin = 0; /* Use /etc/passwd for checking PAP */ -int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ -int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ -char our_name[MAXNAMELEN]; /* Our name for authentication purposes */ -char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ -int explicit_remote = 0; /* User specified explicit remote name */ -int usehostname = 0; /* Use hostname for our_name */ -int disable_defaultip = 0; /* Don't use hostname for default IP adrs */ -int demand = 0; /* do dial-on-demand */ -char *ipparam = NULL; /* Extra parameter for ip up/down scripts */ -int cryptpap; /* Passwords in pap-secrets are encrypted */ -int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ -int holdoff = 30; /* # seconds to pause before reconnecting */ -int refuse_pap = 0; /* Set to say we won't do PAP */ -int refuse_chap = 0; /* Set to say we won't do CHAP */ - -#ifdef MSLANMAN -int ms_lanman = 0; /* Nonzero if use LanMan password instead of NT */ - /* Has meaning only with MS-CHAP challenges */ -#endif - -struct option_info auth_req_info; -struct option_info connector_info; -struct option_info disconnector_info; -struct option_info welcomer_info; -struct option_info devnam_info; -#ifdef PPP_FILTER -struct bpf_program pass_filter;/* Filter program for packets to pass */ -struct bpf_program active_filter; /* Filter program for link-active pkts */ -pcap_t pc; /* Fake struct pcap so we can compile expr */ -#endif - -/* - * Prototypes - */ -static int setdevname(char *, int); -static int setspeed(char *); -static int setdebug(char **); -static int setkdebug(char **); -static int setpassive(char **); -static int setsilent(char **); -static int noopt(char **); -static int setnovj(char **); -static int setnovjccomp(char **); -static int setvjslots(char **); -static int reqpap(char **); -static int nopap(char **); -#ifdef OLD_OPTIONS -static int setupapfile(char **); -#endif -static int nochap(char **); -static int reqchap(char **); -static int noaccomp(char **); -static int noasyncmap(char **); -static int noip(char **); -static int nomagicnumber(char **); -static int setasyncmap(char **); -static int setescape(char **); -static int setmru(char **); -static int setmtu(char **); -#ifdef CBCP_SUPPORT -static int setcbcp(char **); -#endif -static int nomru(char **); -static int nopcomp(char **); -static int setconnector(char **); -static int setdisconnector(char **); -static int setwelcomer(char **); -static int setmaxcon(char **); -static int setmaxconnect(char **); -static int setdomain(char **); -static int setnetmask(char **); -static int setcrtscts(char **); -static int setnocrtscts(char **); -static int setxonxoff(char **); -static int setnodetach(char **); -static int setupdetach(char **); -static int setmodem(char **); -static int setlocal(char **); -static int setlock(char **); -static int setname(char **); -static int setuser(char **); -static int setremote(char **); -static int setauth(char **); -static int setnoauth(char **); -static int readfile(char **); -static int callfile(char **); -static int setdefaultroute(char **); -static int setnodefaultroute(char **); -static int setproxyarp(char **); -static int setnoproxyarp(char **); -static int setpersist(char **); -static int setnopersist(char **); -static int setdologin(char **); -static int setusehostname(char **); -static int setnoipdflt(char **); -static int setlcptimeout(char **); -static int setlcpterm(char **); -static int setlcpconf(char **); -static int setlcpfails(char **); -static int setipcptimeout(char **); -static int setipcpterm(char **); -static int setipcpconf(char **); -static int setipcpfails(char **); -static int setpaptimeout(char **); -static int setpapreqs(char **); -static int setpapreqtime(char **); -static int setchaptimeout(char **); -static int setchapchal(char **); -static int setchapintv(char **); -static int setipcpaccl(char **); -static int setipcpaccr(char **); -static int setlcpechointv(char **); -static int setlcpechofails(char **); -static int noccp(char **); -static int setbsdcomp(char **); -static int setnobsdcomp(char **); -static int setdeflate(char **); -static int setnodeflate(char **); -static int setnodeflatedraft(char **); -static int setdemand(char **); -static int setpred1comp(char **); -static int setnopred1comp(char **); -static int setipparam(char **); -static int setpapcrypt(char **); -static int setidle(char **); -static int setholdoff(char **); -static int setdnsaddr(char **); -static int resetipv6proto(char **); -static int resetipxproto(char **); -static int setwinsaddr(char **); -static int showversion(char **); -static int showhelp(char **); - -#ifdef PPP_FILTER -static int setpdebug(char **); -static int setpassfilter(char **); -static int setactivefilter(char **); -#endif - -#ifdef INET6 -static int setipv6cp_accept_local(char **); -static int setipv6cp_use_ip(char **); -#if defined(SOL2) -static int setipv6cp_use_persistent(char **); -#endif -static int setipv6cptimeout(char **); -static int setipv6cpterm(char **); -static int setipv6cpconf(char **); -static int setipv6cpfails(char **); -static int setipv6proto(char **); -#endif /* INET6 */ - -#ifdef IPX_CHANGE -static int setipxproto(char **); -static int setipxanet(char **); -static int setipxalcl(char **); -static int setipxarmt(char **); -static int setipxnetwork(char **); -static int setipxnode(char **); -static int setipxrouter(char **); -static int setipxname(char **); -static int setipxcptimeout(char **); -static int setipxcpterm(char **); -static int setipxcpconf(char **); -static int setipxcpfails(char **); -#endif /* IPX_CHANGE */ - -#ifdef MSLANMAN -static int setmslanman(char **); -#endif - -static int number_option(char *, u_int32_t *, int); -static int int_option(char *, int *); -static int readable(int fd); - -/* - * Valid arguments. - */ -static struct cmd { - char *cmd_name; - int num_args; - int (*cmd_func)(char **); -} cmds[] = { - {"-all", 0, noopt}, /* Don't request/allow any options (useless) */ - {"noaccomp", 0, noaccomp}, /* Disable Address/Control compression */ - {"-ac", 0, noaccomp}, /* Disable Address/Control compress */ - {"default-asyncmap", 0, noasyncmap}, /* Disable asyncmap negoatiation */ - {"-am", 0, noasyncmap}, /* Disable asyncmap negotiation */ - {"-as", 1, setasyncmap}, /* set the desired async map */ - {"-d", 0, setdebug}, /* Increase debugging level */ - {"nodetach", 0, setnodetach}, /* Don't detach from controlling tty */ - {"-detach", 0, setnodetach}, /* don't fork */ - {"updetach", 0, setupdetach}, /* Detach once an NP has come up */ - {"noip", 0, noip}, /* Disable IP and IPCP */ - {"-ip", 0, noip}, /* Disable IP and IPCP */ - {"nomagic", 0, nomagicnumber}, /* Disable magic number negotiation */ - {"-mn", 0, nomagicnumber}, /* Disable magic number negotiation */ - {"default-mru", 0, nomru}, /* Disable MRU negotiation */ - {"-mru", 0, nomru}, /* Disable mru negotiation */ - {"-p", 0, setpassive}, /* Set passive mode */ - {"nopcomp", 0, nopcomp}, /* Disable protocol field compression */ - {"-pc", 0, nopcomp}, /* Disable protocol field compress */ -#if OLD_OPTIONS - {"+ua", 1, setupapfile}, /* Get PAP user and password from file */ -#endif - {"require-pap", 0, reqpap}, /* Require PAP authentication from peer */ - {"+pap", 0, reqpap}, /* Require PAP auth from peer */ - {"refuse-pap", 0, nopap}, /* Don't agree to auth to peer with PAP */ - {"-pap", 0, nopap}, /* Don't allow UPAP authentication with peer */ - {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */ - {"+chap", 0, reqchap}, /* Require CHAP authentication from peer */ - {"refuse-chap", 0, nochap}, /* Don't agree to auth to peer with CHAP */ - {"-chap", 0, nochap}, /* Don't allow CHAP authentication with peer */ - {"novj", 0, setnovj}, /* Disable VJ compression */ - {"-vj", 0, setnovj}, /* disable VJ compression */ - {"novjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */ - {"-vjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */ - {"vj-max-slots", 1, setvjslots}, /* Set maximum VJ header slots */ - {"asyncmap", 1, setasyncmap}, /* set the desired async map */ - {"escape", 1, setescape}, /* set chars to escape on transmission */ - {"connect", 1, setconnector}, /* A program to set up a connection */ - {"disconnect", 1, setdisconnector}, /* program to disconnect serial dev. */ - {"welcome", 1, setwelcomer},/* Script to welcome client */ - {"connect-max-attempts", 1, setmaxcon}, /* maximum # connect attempts */ - {"maxconnect", 1, setmaxconnect}, /* specify a maximum connect time */ - {"crtscts", 0, setcrtscts}, /* set h/w flow control */ - {"nocrtscts", 0, setnocrtscts}, /* clear h/w flow control */ - {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */ - {"xonxoff", 0, setxonxoff}, /* set s/w flow control */ - {"debug", 0, setdebug}, /* Increase debugging level */ - {"kdebug", 1, setkdebug}, /* Enable kernel-level debugging */ - {"domain", 1, setdomain}, /* Add given domain name to hostname*/ - {"mru", 1, setmru}, /* Set MRU value for negotiation */ - {"mtu", 1, setmtu}, /* Set our MTU */ -#ifdef CBCP_SUPPORT - {"callback", 1, setcbcp}, /* Ask for callback */ -#endif - {"netmask", 1, setnetmask}, /* set netmask */ - {"passive", 0, setpassive}, /* Set passive mode */ - {"silent", 0, setsilent}, /* Set silent mode */ - {"modem", 0, setmodem}, /* Use modem control lines */ - {"local", 0, setlocal}, /* Don't use modem control lines */ - {"lock", 0, setlock}, /* Lock serial device (with lock file) */ - {"name", 1, setname}, /* Set local name for authentication */ - {"user", 1, setuser}, /* Set name for auth with peer */ - {"usehostname", 0, setusehostname}, /* Must use hostname for auth. */ - {"remotename", 1, setremote}, /* Set remote name for authentication */ - {"auth", 0, setauth}, /* Require authentication from peer */ - {"noauth", 0, setnoauth}, /* Don't require peer to authenticate */ - {"file", 1, readfile}, /* Take options from a file */ - {"call", 1, callfile}, /* Take options from a privileged file */ - {"defaultroute", 0, setdefaultroute}, /* Add default route */ - {"nodefaultroute", 0, setnodefaultroute}, /* disable defaultroute option */ - {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */ - {"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */ - {"noproxyarp", 0, setnoproxyarp}, /* disable proxyarp option */ - {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */ - {"persist", 0, setpersist}, /* Keep on reopening connection after close */ - {"nopersist", 0, setnopersist}, /* Turn off persist option */ - {"demand", 0, setdemand}, /* Dial on demand */ - {"login", 0, setdologin}, /* Use system password database for UPAP */ - {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */ - {"lcp-echo-failure", 1, setlcpechofails}, /* consecutive echo failures */ - {"lcp-echo-interval", 1, setlcpechointv}, /* time for lcp echo events */ - {"lcp-restart", 1, setlcptimeout}, /* Set timeout for LCP */ - {"lcp-max-terminate", 1, setlcpterm}, /* Set max #xmits for term-reqs */ - {"lcp-max-configure", 1, setlcpconf}, /* Set max #xmits for conf-reqs */ - {"lcp-max-failure", 1, setlcpfails}, /* Set max #conf-naks for LCP */ - {"ipcp-restart", 1, setipcptimeout}, /* Set timeout for IPCP */ - {"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */ - {"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */ - {"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */ - {"pap-restart", 1, setpaptimeout}, /* Set retransmit timeout for PAP */ - {"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */ - {"pap-timeout", 1, setpapreqtime}, /* Set time limit for peer PAP auth. */ - {"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */ - {"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */ - {"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */ - {"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */ - {"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */ - {"noccp", 0, noccp}, /* Disable CCP negotiation */ - {"-ccp", 0, noccp}, /* Disable CCP negotiation */ - {"bsdcomp", 1, setbsdcomp}, /* request BSD-Compress */ - {"nobsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */ - {"-bsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */ - {"deflate", 1, setdeflate}, /* request Deflate compression */ - {"nodeflate", 0, setnodeflate}, /* don't allow Deflate compression */ - {"-deflate", 0, setnodeflate}, /* don't allow Deflate compression */ - {"nodeflatedraft", 0, setnodeflatedraft}, /* don't use draft deflate # */ - {"predictor1", 0, setpred1comp}, /* request Predictor-1 */ - {"nopredictor1", 0, setnopred1comp},/* don't allow Predictor-1 */ - {"-predictor1", 0, setnopred1comp}, /* don't allow Predictor-1 */ - {"ipparam", 1, setipparam}, /* set ip script parameter */ - {"papcrypt", 0, setpapcrypt}, /* PAP passwords encrypted */ - {"idle", 1, setidle}, /* idle time limit (seconds) */ - {"holdoff", 1, setholdoff}, /* set holdoff time (seconds) */ -/* backwards compat hack */ - {"dns1", 1, setdnsaddr}, /* DNS address for the peer's use */ - {"dns2", 1, setdnsaddr}, /* DNS address for the peer's use */ -/* end compat hack */ - {"ms-dns", 1, setdnsaddr}, /* DNS address for the peer's use */ - {"ms-wins", 1, setwinsaddr}, /* Nameserver for SMB over TCP/IP for peer */ - {"noipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */ - {"-ipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */ - {"noipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */ - {"-ipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */ - {"--version", 0, showversion}, /* Show version number */ - {"--help", 0, showhelp}, /* Show brief listing of options */ - {"-h", 0, showhelp}, /* ditto */ - -#ifdef PPP_FILTER - {"pdebug", 1, setpdebug}, /* libpcap debugging */ - {"pass-filter", 1, setpassfilter}, /* set filter for packets to pass */ - {"active-filter", 1, setactivefilter}, /* set filter for active pkts */ -#endif - -#ifdef INET6 - {"ipv6", 1, setifaceid}, /* Set interface id for IPV6" */ - {"+ipv6", 0, setipv6proto}, /* Enable IPv6 and IPv6CP */ - {"ipv6cp-accept-local", 0, setipv6cp_accept_local}, /* Accept peer's iface id for us */ - {"ipv6cp-use-ipaddr", 0, setipv6cp_use_ip}, /* Use IPv4 addr as iface id */ -#if defined(SOL2) - {"ipv6cp-use-persistent", 0, setipv6cp_use_persistent}, /* Use uniquely-available persistent value for link local addr */ -#endif - {"ipv6cp-restart", 1, setipv6cptimeout}, /* Set timeout for IPv6CP */ - {"ipv6cp-max-terminate", 1, setipv6cpterm}, /* max #xmits for term-reqs */ - {"ipv6cp-max-configure", 1, setipv6cpconf}, /* max #xmits for conf-reqs */ - {"ipv6cp-max-failure", 1, setipv6cpfails}, /* max #conf-naks for IPv6CP */ -#endif - -#ifdef IPX_CHANGE - {"ipx-network", 1, setipxnetwork}, /* IPX network number */ - {"ipxcp-accept-network", 0, setipxanet}, /* Accept peer netowrk */ - {"ipx-node", 1, setipxnode}, /* IPX node number */ - {"ipxcp-accept-local", 0, setipxalcl}, /* Accept our address */ - {"ipxcp-accept-remote", 0, setipxarmt}, /* Accept peer's address */ - {"ipx-routing", 1, setipxrouter}, /* IPX routing proto number */ - {"ipx-router-name", 1, setipxname}, /* IPX router name */ - {"ipxcp-restart", 1, setipxcptimeout}, /* Set timeout for IPXCP */ - {"ipxcp-max-terminate", 1, setipxcpterm}, /* max #xmits for term-reqs */ - {"ipxcp-max-configure", 1, setipxcpconf}, /* max #xmits for conf-reqs */ - {"ipxcp-max-failure", 1, setipxcpfails}, /* max #conf-naks for IPXCP */ -#if 0 - {"ipx-compression", 1, setipxcompression}, /* IPX compression number */ -#endif - {"ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */ - {"+ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */ -#endif /* IPX_CHANGE */ - -#ifdef MSLANMAN - {"ms-lanman", 0, setmslanman}, /* Use LanMan psswd when using MS-CHAP */ -#endif - - {NULL, 0, NULL} -}; - - -#ifndef IMPLEMENTATION -#define IMPLEMENTATION "" -#endif - -static const char usage_string[] = "\ -pppd version %s patch level %d%s\n\ -Usage: %s [ options ], where options are:\n\ - <device> Communicate over the named device\n\ - <speed> Set the baud rate to <speed>\n\ - <loc>:<rem> Set the local and/or remote interface IP\n\ - addresses. Either one may be omitted.\n\ - asyncmap <n> Set the desired async map to hex <n>\n\ - auth Require authentication from peer\n\ - connect <p> Invoke shell command <p> to set up the serial line\n\ - crtscts Use hardware RTS/CTS flow control\n\ - defaultroute Add default route through interface\n\ - file <f> Take options from file <f>\n\ - modem Use modem control lines\n\ - mru <n> Set MRU value to <n> for negotiation\n\ -See pppd(8) for more options.\n\ -"; - -static char *current_option; /* the name of the option being parsed */ -static int privileged_option; /* set iff the current option came from root */ -static char *option_source; /* string saying where the option came from */ - -/* - * parse_args - parse a string of arguments from the command line. - */ -int -parse_args(argc, argv) - int argc; - char **argv; -{ - char *arg; - struct cmd *cmdp; - int ret; - - privileged_option = privileged; - option_source = "command line"; - while (argc > 0) { - arg = *argv++; - --argc; - - /* - * First see if it's a command. - */ - for (cmdp = cmds; cmdp->cmd_name; cmdp++) - if (!strcmp(arg, cmdp->cmd_name)) - break; - - if (cmdp->cmd_name != NULL) { - if (argc < cmdp->num_args) { - option_error("too few parameters for option %s", arg); - return 0; - } - current_option = arg; - if (!(*cmdp->cmd_func)(argv)) - return 0; - argc -= cmdp->num_args; - argv += cmdp->num_args; - - } else { - /* - * Maybe a tty name, speed or IP address? - */ - if ((ret = setdevname(arg, 0)) == 0 - && (ret = setspeed(arg)) == 0 - && (ret = setipaddr(arg)) == 0) { - option_error("unrecognized option '%s'", arg); - usage(); - return 0; - } - if (ret < 0) /* error */ - return 0; - } - } - return 1; -} - -/* - * scan_args - scan the command line arguments to get the tty name, - * if specified. - */ -void -scan_args(argc, argv) - int argc; - char **argv; -{ - char *arg; - struct cmd *cmdp; - - while (argc > 0) { - arg = *argv++; - --argc; - - /* Skip options and their arguments */ - for (cmdp = cmds; cmdp->cmd_name; cmdp++) - if (!strcmp(arg, cmdp->cmd_name)) - break; - - if (cmdp->cmd_name != NULL) { - argc -= cmdp->num_args; - argv += cmdp->num_args; - continue; - } - - /* Check if it's a tty name and copy it if so */ - (void) setdevname(arg, 1); - } -} - -/* - * usage - print out a message telling how to use the program. - */ -void -usage() -{ - if (phase == PHASE_INITIALIZE) - fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION, - progname); -} - -/* - * showhelp - print out usage message and exit. - */ -static int -showhelp(argv) - char **argv; -{ - if (phase == PHASE_INITIALIZE) { - usage(); - exit(0); - } - return 0; -} - -/* - * showversion - print out the version number and exit. - */ -static int -showversion(argv) - char **argv; -{ - if (phase == PHASE_INITIALIZE) { - fprintf(stderr, "pppd version %s patch level %d%s\n", - VERSION, PATCHLEVEL, IMPLEMENTATION); - exit(0); - } - return 0; -} - -/* - * options_from_file - Read a string of options from a file, - * and interpret them. - */ -int -options_from_file(filename, must_exist, check_prot, priv) - char *filename; - int must_exist; - int check_prot; - int priv; -{ - FILE *f; - int i, newline, ret; - struct cmd *cmdp; - int oldpriv; - char *argv[MAXARGS]; - char args[MAXARGS][MAXWORDLEN]; - char cmd[MAXWORDLEN]; - - if ((f = fopen(filename, "r")) == NULL) { - if (!must_exist && errno == ENOENT) - return 1; - option_error("Can't open options file %s: %m", filename); - return 0; - } - if (check_prot && !readable(fileno(f))) { - option_error("Can't open options file %s: access denied", filename); - fclose(f); - return 0; - } - - oldpriv = privileged_option; - privileged_option = priv; - ret = 0; - while (getword(f, cmd, &newline, filename)) { - /* - * First see if it's a command. - */ - for (cmdp = cmds; cmdp->cmd_name; cmdp++) - if (!strcmp(cmd, cmdp->cmd_name)) - break; - - if (cmdp->cmd_name != NULL) { - for (i = 0; i < cmdp->num_args; ++i) { - if (!getword(f, args[i], &newline, filename)) { - option_error( - "In file %s: too few parameters for option '%s'", - filename, cmd); - goto err; - } - argv[i] = args[i]; - } - current_option = cmd; - if (!(*cmdp->cmd_func)(argv)) - goto err; - - } else { - /* - * Maybe a tty name, speed or IP address? - */ - if ((i = setdevname(cmd, 0)) == 0 - && (i = setspeed(cmd)) == 0 - && (i = setipaddr(cmd)) == 0) { - option_error("In file %s: unrecognized option '%s'", - filename, cmd); - goto err; - } - if (i < 0) /* error */ - goto err; - } - } - ret = 1; - -err: - fclose(f); - privileged_option = oldpriv; - return ret; -} - -/* - * options_from_user - See if the use has a ~/.ppprc file, - * and if so, interpret options from it. - */ -int -options_from_user() -{ - char *user, *path, *file; - int ret; - struct passwd *pw; - - pw = getpwuid(getuid()); - if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) - return 1; - file = _PATH_USEROPT; - path = malloc(strlen(user) + strlen(file) + 2); - if (path == NULL) - novm("init file name"); - strcpy(path, user); - strcat(path, "/"); - strcat(path, file); - ret = options_from_file(path, 0, 1, privileged); - free(path); - return ret; -} - -/* - * options_for_tty - See if an options file exists for the serial - * device, and if so, interpret options from it. - */ -int -options_for_tty() -{ - char *dev, *path, *p; - int ret; - - dev = devnam; - if (strncmp(dev, _PATH_DEV, sizeof _PATH_DEV - 1) == 0) - dev += 5; - if (strcmp(dev, "tty") == 0) - return 1; /* don't look for /etc/ppp/options.tty */ - path = malloc(strlen(_PATH_TTYOPT) + strlen(dev) + 1); - if (path == NULL) - novm("tty init file name"); - strcpy(path, _PATH_TTYOPT); - /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */ - for (p = path + strlen(path); *dev != 0; ++dev) - *p++ = (*dev == '/'? '.': *dev); - *p = 0; - ret = options_from_file(path, 0, 0, 1); - free(path); - return ret; -} - -/* - * option_error - print a message about an error in an option. - * The message is logged, and also sent to - * stderr if phase == PHASE_INITIALIZE. - */ -void -option_error __V((char *fmt, ...)) -{ - va_list args; - char buf[256]; - -#if __STDC__ - va_start(args, fmt); -#else - char *fmt; - va_start(args); - fmt = va_arg(args, char *); -#endif - vfmtmsg(buf, sizeof(buf), fmt, args); - va_end(args); - if (phase == PHASE_INITIALIZE) - fprintf(stderr, "%s: %s\n", progname, buf); - syslog(LOG_ERR, "%s", buf); -} - -/* - * readable - check if a file is readable by the real user. - */ -static int -readable(fd) - int fd; -{ - uid_t uid; - int ngroups, i; - struct stat sbuf; - GIDSET_TYPE groups[NGROUPS_MAX]; - - uid = getuid(); - if (uid == 0) - return 1; - if (fstat(fd, &sbuf) != 0) - return 0; - if (sbuf.st_uid == uid) - return sbuf.st_mode & S_IRUSR; - if (sbuf.st_gid == getgid()) - return sbuf.st_mode & S_IRGRP; - ngroups = getgroups(NGROUPS_MAX, groups); - for (i = 0; i < ngroups; ++i) - if (sbuf.st_gid == groups[i]) - return sbuf.st_mode & S_IRGRP; - return sbuf.st_mode & S_IROTH; -} - -/* - * Read a word from a file. - * Words are delimited by white-space or by quotes (" or '). - * Quotes, white-space and \ may be escaped with \. - * \<newline> is ignored. - */ -int -getword(f, word, newlinep, filename) - FILE *f; - char *word; - int *newlinep; - char *filename; -{ - int c, len, escape; - int quoted, comment; - int value, digit, got, n; - -#define isoctal(c) ((c) >= '0' && (c) < '8') - - *newlinep = 0; - len = 0; - escape = 0; - comment = 0; - - /* - * First skip white-space and comments. - */ - for (;;) { - c = getc(f); - if (c == EOF) - break; - - /* - * A newline means the end of a comment; backslash-newline - * is ignored. Note that we cannot have escape && comment. - */ - if (c == '\n') { - if (!escape) { - *newlinep = 1; - comment = 0; - } else - escape = 0; - continue; - } - - /* - * Ignore characters other than newline in a comment. - */ - if (comment) - continue; - - /* - * If this character is escaped, we have a word start. - */ - if (escape) - break; - - /* - * If this is the escape character, look at the next character. - */ - if (c == '\\') { - escape = 1; - continue; - } - - /* - * If this is the start of a comment, ignore the rest of the line. - */ - if (c == '#') { - comment = 1; - continue; - } - - /* - * A non-whitespace character is the start of a word. - */ - if (!isspace(c)) - break; - } - - /* - * Save the delimiter for quoted strings. - */ - if (!escape && (c == '"' || c == '\'')) { - quoted = c; - c = getc(f); - } else - quoted = 0; - - /* - * Process characters until the end of the word. - */ - while (c != EOF) { - if (escape) { - /* - * This character is escaped: backslash-newline is ignored, - * various other characters indicate particular values - * as for C backslash-escapes. - */ - escape = 0; - if (c == '\n') { - c = getc(f); - continue; - } - - got = 0; - switch (c) { - case 'a': - value = '\a'; - break; - case 'b': - value = '\b'; - break; - case 'f': - value = '\f'; - break; - case 'n': - value = '\n'; - break; - case 'r': - value = '\r'; - break; - case 's': - value = ' '; - break; - case 't': - value = '\t'; - break; - - default: - if (isoctal(c)) { - /* - * \ddd octal sequence - */ - value = 0; - for (n = 0; n < 3 && isoctal(c); ++n) { - value = (value << 3) + (c & 07); - c = getc(f); - } - got = 1; - break; - } - - if (c == 'x') { - /* - * \x<hex_string> sequence - */ - value = 0; - c = getc(f); - for (n = 0; n < 2 && isxdigit(c); ++n) { - digit = toupper(c) - '0'; - if (digit > 10) - digit += '0' + 10 - 'A'; - value = (value << 4) + digit; - c = getc (f); - } - got = 1; - break; - } - - /* - * Otherwise the character stands for itself. - */ - value = c; - break; - } - - /* - * Store the resulting character for the escape sequence. - */ - if (len < MAXWORDLEN-1) - word[len] = value; - ++len; - - if (!got) - c = getc(f); - continue; - - } - - /* - * Not escaped: see if we've reached the end of the word. - */ - if (quoted) { - if (c == quoted) - break; - } else { - if (isspace(c) || c == '#') { - ungetc (c, f); - break; - } - } - - /* - * Backslash starts an escape sequence. - */ - if (c == '\\') { - escape = 1; - c = getc(f); - continue; - } - - /* - * An ordinary character: store it in the word and get another. - */ - if (len < MAXWORDLEN-1) - word[len] = c; - ++len; - - c = getc(f); - } - - /* - * End of the word: check for errors. - */ - if (c == EOF) { - if (ferror(f)) { - if (errno == 0) - errno = EIO; - option_error("Error reading %s: %m", filename); - die(1); - } - /* - * If len is zero, then we didn't find a word before the - * end of the file. - */ - if (len == 0) - return 0; - } - - /* - * Warn if the word was too long, and append a terminating null. - */ - if (len >= MAXWORDLEN) { - option_error("warning: word in file %s too long (%.20s...)", - filename, word); - len = MAXWORDLEN - 1; - } - word[len] = 0; - - return 1; - -#undef isoctal - -} - -/* - * number_option - parse an unsigned numeric parameter for an option. - */ -static int -number_option(str, valp, base) - char *str; - u_int32_t *valp; - int base; -{ - char *ptr; - - *valp = strtoul(str, &ptr, base); - if (ptr == str) { - option_error("invalid numeric parameter '%s' for %s option", - str, current_option); - return 0; - } - return 1; -} - - -/* - * int_option - like number_option, but valp is int *, - * the base is assumed to be 0, and *valp is not changed - * if there is an error. - */ -static int -int_option(str, valp) - char *str; - int *valp; -{ - u_int32_t v; - - if (!number_option(str, &v, 0)) - return 0; - *valp = (int) v; - return 1; -} - - -/* - * The following procedures parse options. - */ - -/* - * readfile - take commands from a file. - */ -static int -readfile(argv) - char **argv; -{ - return options_from_file(*argv, 1, 1, privileged_option); -} - -/* - * callfile - take commands from /etc/ppp/peers/<name>. - * Name may not contain /../, start with / or ../, or end in /.. - */ -static int -callfile(argv) - char **argv; -{ - char *fname, *arg, *p; - int l, ok; - - arg = *argv; - ok = 1; - if (arg[0] == '/' || arg[0] == 0) - ok = 0; - else { - for (p = arg; *p != 0; ) { - if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) { - ok = 0; - break; - } - while (*p != '/' && *p != 0) - ++p; - if (*p == '/') - ++p; - } - } - if (!ok) { - option_error("call option value may not contain .. or start with /"); - return 0; - } - - l = strlen(arg) + strlen(_PATH_PEERFILES) + 1; - if ((fname = (char *) malloc(l)) == NULL) - novm("call file name"); - strcpy(fname, _PATH_PEERFILES); - strcat(fname, arg); - - ok = options_from_file(fname, 1, 1, 1); - - free(fname); - return ok; -} - - -/* - * setdebug - Set debug (command line argument). - */ -static int -setdebug(argv) - char **argv; -{ - debug++; - return (1); -} - -/* - * setkdebug - Set kernel debugging level. - */ -static int -setkdebug(argv) - char **argv; -{ - return int_option(*argv, &kdebugflag); -} - -#ifdef PPP_FILTER -/* - * setpdebug - Set libpcap debugging level. - */ -static int -setpdebug(argv) - char **argv; -{ - return int_option(*argv, &dflag); -} - -/* - * setpassfilter - Set the pass filter for packets - */ -static int -setpassfilter(argv) - char **argv; -{ - pc.linktype = DLT_PPP; - pc.snapshot = PPP_HDRLEN; - - if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0) - return 1; - option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc)); - return 0; -} - -/* - * setactivefilter - Set the active filter for packets - */ -static int -setactivefilter(argv) - char **argv; -{ - pc.linktype = DLT_PPP; - pc.snapshot = PPP_HDRLEN; - - if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0) - return 1; - option_error("error in active-filter expression: %s\n", pcap_geterr(&pc)); - return 0; -} -#endif - -/* - * noopt - Disable all options. - */ -static int -noopt(argv) - char **argv; -{ - BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); - BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); - BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options)); - BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options)); - -#ifdef IPX_CHANGE - BZERO((char *) &ipxcp_wantoptions[0], sizeof (struct ipxcp_options)); - BZERO((char *) &ipxcp_allowoptions[0], sizeof (struct ipxcp_options)); -#endif /* IPX_CHANGE */ - - return (1); -} - -/* - * noaccomp - Disable Address/Control field compression negotiation. - */ -static int -noaccomp(argv) - char **argv; -{ - lcp_wantoptions[0].neg_accompression = 0; - lcp_allowoptions[0].neg_accompression = 0; - return (1); -} - - -/* - * noasyncmap - Disable async map negotiation. - */ -static int -noasyncmap(argv) - char **argv; -{ - lcp_wantoptions[0].neg_asyncmap = 0; - lcp_allowoptions[0].neg_asyncmap = 0; - return (1); -} - - -/* - * noip - Disable IP and IPCP. - */ -static int -noip(argv) - char **argv; -{ - ipcp_protent.enabled_flag = 0; - return (1); -} - - -/* - * nomagicnumber - Disable magic number negotiation. - */ -static int -nomagicnumber(argv) - char **argv; -{ - lcp_wantoptions[0].neg_magicnumber = 0; - lcp_allowoptions[0].neg_magicnumber = 0; - return (1); -} - - -/* - * nomru - Disable mru negotiation. - */ -static int -nomru(argv) - char **argv; -{ - lcp_wantoptions[0].neg_mru = 0; - lcp_allowoptions[0].neg_mru = 0; - return (1); -} - - -/* - * setmru - Set MRU for negotiation. - */ -static int -setmru(argv) - char **argv; -{ - u_int32_t mru; - - if (!number_option(*argv, &mru, 0)) - return 0; - lcp_wantoptions[0].mru = mru; - lcp_wantoptions[0].neg_mru = 1; - return (1); -} - - -/* - * setmru - Set the largest MTU we'll use. - */ -static int -setmtu(argv) - char **argv; -{ - u_int32_t mtu; - - if (!number_option(*argv, &mtu, 0)) - return 0; - if (mtu < MINMRU || mtu > MAXMRU) { - option_error("mtu option value of %u is too %s", mtu, - (mtu < MINMRU? "small": "large")); - return 0; - } - lcp_allowoptions[0].mru = mtu; - return (1); -} - -#ifdef CBCP_SUPPORT -static int -setcbcp(argv) - char **argv; -{ - lcp_wantoptions[0].neg_cbcp = 1; - cbcp_protent.enabled_flag = 1; - cbcp[0].us_number = strdup(*argv); - if (cbcp[0].us_number == 0) - novm("callback number"); - cbcp[0].us_type |= (1 << CB_CONF_USER); - cbcp[0].us_type |= (1 << CB_CONF_ADMIN); - return (1); -} -#endif - -/* - * nopcomp - Disable Protocol field compression negotiation. - */ -static int -nopcomp(argv) - char **argv; -{ - lcp_wantoptions[0].neg_pcompression = 0; - lcp_allowoptions[0].neg_pcompression = 0; - return (1); -} - - -/* - * setpassive - Set passive mode (don't give up if we time out sending - * LCP configure-requests). - */ -static int -setpassive(argv) - char **argv; -{ - lcp_wantoptions[0].passive = 1; - return (1); -} - - -/* - * setsilent - Set silent mode (don't start sending LCP configure-requests - * until we get one from the peer). - */ -static int -setsilent(argv) - char **argv; -{ - lcp_wantoptions[0].silent = 1; - return 1; -} - - -/* - * nopap - Disable PAP authentication with peer. - */ -static int -nopap(argv) - char **argv; -{ - refuse_pap = 1; - return (1); -} - - -/* - * reqpap - Require PAP authentication from peer. - */ -static int -reqpap(argv) - char **argv; -{ - lcp_wantoptions[0].neg_upap = 1; - setauth(NULL); - return 1; -} - -#if OLD_OPTIONS -/* - * setupapfile - specifies UPAP info for authenticating with peer. - */ -static int -setupapfile(argv) - char **argv; -{ - FILE * ufile; - int l; - - lcp_allowoptions[0].neg_upap = 1; - - /* open user info file */ - if ((ufile = fopen(*argv, "r")) == NULL) { - option_error("unable to open user login data file %s", *argv); - return 0; - } - if (!readable(fileno(ufile))) { - option_error("%s: access denied", *argv); - return 0; - } - check_access(ufile, *argv); - - /* get username */ - if (fgets(user, MAXNAMELEN - 1, ufile) == NULL - || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ - option_error("unable to read user login data file %s", *argv); - return 0; - } - fclose(ufile); - - /* get rid of newlines */ - l = strlen(user); - if (l > 0 && user[l-1] == '\n') - user[l-1] = 0; - l = strlen(passwd); - if (l > 0 && passwd[l-1] == '\n') - passwd[l-1] = 0; - - return (1); -} -#endif - -/* - * nochap - Disable CHAP authentication with peer. - */ -static int -nochap(argv) - char **argv; -{ - refuse_chap = 1; - return (1); -} - - -/* - * reqchap - Require CHAP authentication from peer. - */ -static int -reqchap(argv) - char **argv; -{ - lcp_wantoptions[0].neg_chap = 1; - setauth(NULL); - return (1); -} - - -/* - * setnovj - disable vj compression - */ -static int -setnovj(argv) - char **argv; -{ - ipcp_wantoptions[0].neg_vj = 0; - ipcp_allowoptions[0].neg_vj = 0; - return (1); -} - - -/* - * setnovjccomp - disable VJ connection-ID compression - */ -static int -setnovjccomp(argv) - char **argv; -{ - ipcp_wantoptions[0].cflag = 0; - ipcp_allowoptions[0].cflag = 0; - return 1; -} - - -/* - * setvjslots - set maximum number of connection slots for VJ compression - */ -static int -setvjslots(argv) - char **argv; -{ - int value; - - if (!int_option(*argv, &value)) - return 0; - if (value < 2 || value > 16) { - option_error("vj-max-slots value must be between 2 and 16"); - return 0; - } - ipcp_wantoptions [0].maxslotindex = - ipcp_allowoptions[0].maxslotindex = value - 1; - return 1; -} - - -/* - * setconnector - Set a program to connect to a serial line - */ -static int -setconnector(argv) - char **argv; -{ - connector = strdup(*argv); - if (connector == NULL) - novm("connect script"); - connector_info.priv = privileged_option; - connector_info.source = option_source; - - return (1); -} - -/* - * setdisconnector - Set a program to disconnect from the serial line - */ -static int -setdisconnector(argv) - char **argv; -{ - disconnector = strdup(*argv); - if (disconnector == NULL) - novm("disconnect script"); - disconnector_info.priv = privileged_option; - disconnector_info.source = option_source; - - return (1); -} - -/* - * setwelcomer - Set a program to welcome a client after connection - */ -static int -setwelcomer(argv) - char **argv; -{ - welcomer = strdup(*argv); - if (welcomer == NULL) - novm("welcome script"); - welcomer_info.priv = privileged_option; - welcomer_info.source = option_source; - - return (1); -} - -static int -setmaxcon(argv) - char **argv; -{ - return int_option(*argv, &max_con_attempts); -} - -/* - * setmaxconnect - Set the maximum connect time - */ -static int -setmaxconnect(argv) - char **argv; -{ - int value; - - if (!int_option(*argv, &value)) - return 0; - if (value < 0) { - option_error("maxconnect time must be positive"); - return 0; - } - if (maxconnect > 0 && (value == 0 || value > maxconnect)) { - option_error("maxconnect time cannot be increased"); - return 0; - } - maxconnect = value; - return 1; -} - -/* - * setdomain - Set domain name to append to hostname - */ -static int -setdomain(argv) - char **argv; -{ - if (!privileged_option) { - option_error("using the domain option requires root privilege"); - return 0; - } - gethostname(hostname, MAXNAMELEN); - if (**argv != 0) { - if (**argv != '.') - strncat(hostname, ".", MAXNAMELEN - strlen(hostname)); - strncat(hostname, *argv, MAXNAMELEN - strlen(hostname)); - } - hostname[MAXNAMELEN-1] = 0; - return (1); -} - - -/* - * setasyncmap - add bits to asyncmap (what we request peer to escape). - */ -static int -setasyncmap(argv) - char **argv; -{ - u_int32_t asyncmap; - - if (!number_option(*argv, &asyncmap, 16)) - return 0; - lcp_wantoptions[0].asyncmap |= asyncmap; - lcp_wantoptions[0].neg_asyncmap = 1; - return(1); -} - - -/* - * setescape - add chars to the set we escape on transmission. - */ -static int -setescape(argv) - char **argv; -{ - int n, ret; - char *p, *endp; - - p = *argv; - ret = 1; - while (*p) { - n = strtol(p, &endp, 16); - if (p == endp) { - option_error("escape parameter contains invalid hex number '%s'", - p); - return 0; - } - p = endp; - if (n < 0 || (0x20 <= n && n <= 0x3F) || n == 0x5E || n > 0xFF) { - option_error("can't escape character 0x%x", n); - ret = 0; - } else - xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); - while (*p == ',' || *p == ' ') - ++p; - } - return ret; -} - - -/* - * setspeed - Set the speed. - */ -static int -setspeed(arg) - char *arg; -{ - char *ptr; - int spd; - - spd = strtol(arg, &ptr, 0); - if (ptr == arg || *ptr != 0 || spd == 0) - return 0; - inspeed = spd; - return 1; -} - - -/* - * setdevname - Set the device name. - */ -static int -setdevname(cp, quiet) - char *cp; - int quiet; -{ - struct stat statbuf; - char dev[MAXPATHLEN]; - - if (*cp == 0) - return 0; - - if (strncmp(_PATH_DEV, cp, sizeof _PATH_DEV - 1) != 0) { - strcpy(dev, _PATH_DEV); - strncat(dev, cp, MAXPATHLEN - sizeof _PATH_DEV - 1); - dev[MAXPATHLEN-1] = 0; - cp = dev; - } - - /* - * Check if there is a device by this name. - */ - if (stat(cp, &statbuf) < 0) { - if (errno == ENOENT || quiet) - return 0; - option_error("Couldn't stat %s: %m", cp); - return -1; - } - - (void) strncpy(devnam, cp, MAXPATHLEN); - devnam[MAXPATHLEN-1] = 0; - default_device = FALSE; - devnam_info.priv = privileged_option; - devnam_info.source = option_source; - - return 1; -} - - -/* - * setipaddr - Set the IP address - */ -int -setipaddr(arg) - char *arg; -{ - struct hostent *hp; - char *colon; - u_int32_t local, remote; - ipcp_options *wo = &ipcp_wantoptions[0]; - - /* - * IP address pair separated by ":". - */ - if ((colon = strchr(arg, ':')) == NULL) - return 0; - - /* - * If colon first character, then no local addr. - */ - if (colon != arg) { - *colon = '\0'; - if ((local = inet_addr(arg)) == -1) { - if ((hp = gethostbyname(arg)) == NULL) { - option_error("unknown host: %s", arg); - return -1; - } else { - local = *(u_int32_t *)hp->h_addr; - } - } - if (bad_ip_adrs(local)) { - option_error("bad local IP address %s", ip_ntoa(local)); - return -1; - } - if (local != 0) - wo->ouraddr = local; - *colon = ':'; - } - - /* - * If colon last character, then no remote addr. - */ - if (*++colon != '\0') { - if ((remote = inet_addr(colon)) == -1) { - if ((hp = gethostbyname(colon)) == NULL) { - option_error("unknown host: %s", colon); - return -1; - } else { - remote = *(u_int32_t *)hp->h_addr; - if (remote_name[0] == 0) { - strncpy(remote_name, colon, MAXNAMELEN); - remote_name[MAXNAMELEN-1] = 0; - } - } - } - if (bad_ip_adrs(remote)) { - option_error("bad remote IP address %s", ip_ntoa(remote)); - return -1; - } - if (remote != 0) - wo->hisaddr = remote; - } - - return 1; -} - - -/* - * setnoipdflt - disable setipdefault() - */ -static int -setnoipdflt(argv) - char **argv; -{ - disable_defaultip = 1; - return 1; -} - - -/* - * setipcpaccl - accept peer's idea of our address - */ -static int -setipcpaccl(argv) - char **argv; -{ - ipcp_wantoptions[0].accept_local = 1; - return 1; -} - - -/* - * setipcpaccr - accept peer's idea of its address - */ -static int -setipcpaccr(argv) - char **argv; -{ - ipcp_wantoptions[0].accept_remote = 1; - return 1; -} - - -/* - * setnetmask - set the netmask to be used on the interface. - */ -static int -setnetmask(argv) - char **argv; -{ - struct in_addr mask; - - if (!inet_aton(*argv, &mask) || (netmask & ~mask.s_addr)) { - fprintf(stderr, "Invalid netmask %s\n", *argv); - return (0); - } - - netmask = mask.s_addr; - return (1); -} - -static int -setcrtscts(argv) - char **argv; -{ - crtscts = 1; - return (1); -} - -static int -setnocrtscts(argv) - char **argv; -{ - crtscts = -1; - return (1); -} - -static int -setxonxoff(argv) - char **argv; -{ - lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */ - lcp_wantoptions[0].neg_asyncmap = 1; - - crtscts = -2; - return (1); -} - -static int -setnodetach(argv) - char **argv; -{ - nodetach = 1; - return (1); -} - -static int -setupdetach(argv) - char **argv; -{ - nodetach = -1; - return (1); -} - -static int -setdemand(argv) - char **argv; -{ - demand = 1; - persist = 1; - return 1; -} - -static int -setmodem(argv) - char **argv; -{ - modem = 1; - return 1; -} - -static int -setlocal(argv) - char **argv; -{ - modem = 0; - return 1; -} - -static int -setlock(argv) - char **argv; -{ - lockflag = 1; - return 1; -} - -static int -setusehostname(argv) - char **argv; -{ - usehostname = 1; - return 1; -} - -static int -setname(argv) - char **argv; -{ - if (!privileged_option) { - option_error("using the name option requires root privilege"); - return 0; - } - strncpy(our_name, argv[0], MAXNAMELEN); - our_name[MAXNAMELEN-1] = 0; - return 1; -} - -static int -setuser(argv) - char **argv; -{ - strncpy(user, argv[0], MAXNAMELEN); - user[MAXNAMELEN-1] = 0; - return 1; -} - -static int -setremote(argv) - char **argv; -{ - strncpy(remote_name, argv[0], MAXNAMELEN); - remote_name[MAXNAMELEN-1] = 0; - return 1; -} - -static int -setauth(argv) - char **argv; -{ - auth_required = 1; - if (privileged_option > auth_req_info.priv) { - auth_req_info.priv = privileged_option; - auth_req_info.source = option_source; - } - return 1; -} - -static int -setnoauth(argv) - char **argv; -{ - if (auth_required && privileged_option < auth_req_info.priv) { - option_error("cannot override auth option set by %s", - auth_req_info.source); - return 0; - } - auth_required = 0; - return 1; -} - -static int -setdefaultroute(argv) - char **argv; -{ - if (!ipcp_allowoptions[0].default_route) { - option_error("defaultroute option is disabled"); - return 0; - } - ipcp_wantoptions[0].default_route = 1; - return 1; -} - -static int -setnodefaultroute(argv) - char **argv; -{ - ipcp_allowoptions[0].default_route = 0; - ipcp_wantoptions[0].default_route = 0; - return 1; -} - -static int -setproxyarp(argv) - char **argv; -{ - if (!ipcp_allowoptions[0].proxy_arp) { - option_error("proxyarp option is disabled"); - return 0; - } - ipcp_wantoptions[0].proxy_arp = 1; - return 1; -} - -static int -setnoproxyarp(argv) - char **argv; -{ - ipcp_wantoptions[0].proxy_arp = 0; - ipcp_allowoptions[0].proxy_arp = 0; - return 1; -} - -static int -setpersist(argv) - char **argv; -{ - persist = 1; - return 1; -} - -static int -setnopersist(argv) - char **argv; -{ - persist = 0; - return 1; -} - -static int -setdologin(argv) - char **argv; -{ - uselogin = 1; - return 1; -} - -/* - * Functions to set the echo interval for modem-less monitors - */ - -static int -setlcpechointv(argv) - char **argv; -{ - return int_option(*argv, &lcp_echo_interval); -} - -static int -setlcpechofails(argv) - char **argv; -{ - return int_option(*argv, &lcp_echo_fails); -} - -/* - * Functions to set timeouts, max transmits, etc. - */ -static int -setlcptimeout(argv) - char **argv; -{ - return int_option(*argv, &lcp_fsm[0].timeouttime); -} - -static int -setlcpterm(argv) - char **argv; -{ - return int_option(*argv, &lcp_fsm[0].maxtermtransmits); -} - -static int -setlcpconf(argv) - char **argv; -{ - return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits); -} - -static int -setlcpfails(argv) - char **argv; -{ - return int_option(*argv, &lcp_fsm[0].maxnakloops); -} - -static int -setipcptimeout(argv) - char **argv; -{ - return int_option(*argv, &ipcp_fsm[0].timeouttime); -} - -static int -setipcpterm(argv) - char **argv; -{ - return int_option(*argv, &ipcp_fsm[0].maxtermtransmits); -} - -static int -setipcpconf(argv) - char **argv; -{ - return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits); -} - -static int -setipcpfails(argv) - char **argv; -{ - return int_option(*argv, &lcp_fsm[0].maxnakloops); -} - -static int -setpaptimeout(argv) - char **argv; -{ - return int_option(*argv, &upap[0].us_timeouttime); -} - -static int -setpapreqtime(argv) - char **argv; -{ - return int_option(*argv, &upap[0].us_reqtimeout); -} - -static int -setpapreqs(argv) - char **argv; -{ - return int_option(*argv, &upap[0].us_maxtransmits); -} - -static int -setchaptimeout(argv) - char **argv; -{ - return int_option(*argv, &chap[0].timeouttime); -} - -static int -setchapchal(argv) - char **argv; -{ - return int_option(*argv, &chap[0].max_transmits); -} - -static int -setchapintv(argv) - char **argv; -{ - return int_option(*argv, &chap[0].chal_interval); -} - -static int -noccp(argv) - char **argv; -{ - ccp_protent.enabled_flag = 0; - return 1; -} - -static int -setbsdcomp(argv) - char **argv; -{ - int rbits, abits; - char *str, *endp; - - str = *argv; - abits = rbits = strtol(str, &endp, 0); - if (endp != str && *endp == ',') { - str = endp + 1; - abits = strtol(str, &endp, 0); - } - if (*endp != 0 || endp == str) { - option_error("invalid parameter '%s' for bsdcomp option", *argv); - return 0; - } - if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) - || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { - option_error("bsdcomp option values must be 0 or %d .. %d", - BSD_MIN_BITS, BSD_MAX_BITS); - return 0; - } - if (rbits > 0) { - ccp_wantoptions[0].bsd_compress = 1; - ccp_wantoptions[0].bsd_bits = rbits; - } else - ccp_wantoptions[0].bsd_compress = 0; - if (abits > 0) { - ccp_allowoptions[0].bsd_compress = 1; - ccp_allowoptions[0].bsd_bits = abits; - } else - ccp_allowoptions[0].bsd_compress = 0; - return 1; -} - -static int -setnobsdcomp(argv) - char **argv; -{ - ccp_wantoptions[0].bsd_compress = 0; - ccp_allowoptions[0].bsd_compress = 0; - return 1; -} - -static int -setdeflate(argv) - char **argv; -{ - int rbits, abits; - char *str, *endp; - - str = *argv; - abits = rbits = strtol(str, &endp, 0); - if (endp != str && *endp == ',') { - str = endp + 1; - abits = strtol(str, &endp, 0); - } - if (*endp != 0 || endp == str) { - option_error("invalid parameter '%s' for deflate option", *argv); - return 0; - } - if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) - || (abits != 0 && (abits < DEFLATE_MIN_SIZE - || abits > DEFLATE_MAX_SIZE))) { - option_error("deflate option values must be 0 or %d .. %d", - DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); - return 0; - } - if (rbits > 0) { - ccp_wantoptions[0].deflate = 1; - ccp_wantoptions[0].deflate_size = rbits; - } else - ccp_wantoptions[0].deflate = 0; - if (abits > 0) { - ccp_allowoptions[0].deflate = 1; - ccp_allowoptions[0].deflate_size = abits; - } else - ccp_allowoptions[0].deflate = 0; - - /* XXX copy over settings for switch compatibility */ - ccp_wantoptions[0].baddeflate = ccp_wantoptions[0].deflate; - ccp_wantoptions[0].baddeflate_size = ccp_wantoptions[0].deflate_size; - ccp_allowoptions[0].baddeflate = ccp_allowoptions[0].deflate; - ccp_allowoptions[0].baddeflate_size = ccp_allowoptions[0].deflate_size; - - return 1; -} - -static int -setnodeflate(argv) - char **argv; -{ - ccp_wantoptions[0].deflate = 0; - ccp_allowoptions[0].deflate = 0; - return 1; -} - -static int -setnodeflatedraft(argv) - char **argv; -{ - ccp_wantoptions[0].deflate_draft = 0; - ccp_allowoptions[0].deflate_draft = 0; - return 1; -} - -static int -setpred1comp(argv) - char **argv; -{ - ccp_wantoptions[0].predictor_1 = 1; - ccp_allowoptions[0].predictor_1 = 1; - return 1; -} - -static int -setnopred1comp(argv) - char **argv; -{ - ccp_wantoptions[0].predictor_1 = 0; - ccp_allowoptions[0].predictor_1 = 0; - return 1; -} - -static int -setipparam(argv) - char **argv; -{ - ipparam = strdup(*argv); - if (ipparam == NULL) - novm("ipparam string"); - - return 1; -} - -static int -setpapcrypt(argv) - char **argv; -{ - cryptpap = 1; - return 1; -} - -static int -setidle(argv) - char **argv; -{ - return int_option(*argv, &idle_time_limit); -} - -static int -setholdoff(argv) - char **argv; -{ - return int_option(*argv, &holdoff); -} - -/* - * setdnsaddr - set the dns address(es) - */ -static int -setdnsaddr(argv) - char **argv; -{ - u_int32_t dns; - struct hostent *hp; - - dns = inet_addr(*argv); - if (dns == -1) { - if ((hp = gethostbyname(*argv)) == NULL) { - option_error("invalid address parameter '%s' for ms-dns option", - *argv); - return 0; - } - dns = *(u_int32_t *)hp->h_addr; - } - - /* if there is no primary then update it. */ - if (ipcp_allowoptions[0].dnsaddr[0] == 0) - ipcp_allowoptions[0].dnsaddr[0] = dns; - - /* always set the secondary address value to the same value. */ - ipcp_allowoptions[0].dnsaddr[1] = dns; - - return (1); -} - -/* - * setwinsaddr - set the wins address(es) - * This is primrarly used with the Samba package under UNIX or for pointing - * the caller to the existing WINS server on a Windows NT platform. - */ -static int -setwinsaddr(argv) - char **argv; -{ - u_int32_t wins; - struct hostent *hp; - - wins = inet_addr(*argv); - if (wins == -1) { - if ((hp = gethostbyname(*argv)) == NULL) { - option_error("invalid address parameter '%s' for ms-wins option", - *argv); - return 0; - } - wins = *(u_int32_t *)hp->h_addr; - } - - /* if there is no primary then update it. */ - if (ipcp_allowoptions[0].winsaddr[0] == 0) - ipcp_allowoptions[0].winsaddr[0] = wins; - - /* always set the secondary address value to the same value. */ - ipcp_allowoptions[0].winsaddr[1] = wins; - - return (1); -} - -#ifdef INET6 -static int -setipv6cp_accept_local(argv) - char **argv; -{ - ipv6cp_allowoptions[0].accept_local = 1; - return 1; -} - -static int -setipv6cp_use_ip(argv) - char **argv; -{ - ipv6cp_allowoptions[0].use_ip = 1; - return 1; -} - -#if defined(SOL2) -static int -setipv6cp_use_persistent(argv) - char **argv; -{ - ipv6cp_wantoptions[0].use_persistent = 1; - return 1; -} -#endif - -static int -setipv6cptimeout(argv) - char **argv; -{ - return int_option(*argv, &ipv6cp_fsm[0].timeouttime); -} - -static int -setipv6cpterm(argv) - char **argv; -{ - return int_option(*argv, &ipv6cp_fsm[0].maxtermtransmits); -} - -static int -setipv6cpconf(argv) - char **argv; -{ - return int_option(*argv, &ipv6cp_fsm[0].maxconfreqtransmits); -} - -static int -setipv6cpfails(argv) - char **argv; -{ - return int_option(*argv, &ipv6cp_fsm[0].maxnakloops); -} - -static int -setipv6proto(argv) - char **argv; -{ - ipv6cp_protent.enabled_flag = 1; - return 1; -} - -static int -resetipv6proto(argv) - char **argv; -{ - ipv6cp_protent.enabled_flag = 0; - return 1; -} -#else -static int -resetipv6proto(argv) - char **argv; -{ - return 1; -} -#endif /* INET6 */ - -#ifdef IPX_CHANGE -static int -setipxrouter (argv) - char **argv; -{ - ipxcp_wantoptions[0].neg_router = 1; - ipxcp_allowoptions[0].neg_router = 1; - return int_option(*argv, &ipxcp_wantoptions[0].router); -} - -static int -setipxname (argv) - char **argv; -{ - char *dest = ipxcp_wantoptions[0].name; - char *src = *argv; - int count; - char ch; - - ipxcp_wantoptions[0].neg_name = 1; - ipxcp_allowoptions[0].neg_name = 1; - memset (dest, '\0', sizeof (ipxcp_wantoptions[0].name)); - - count = 0; - while (*src) { - ch = *src++; - if (! isalnum (ch) && ch != '_') { - option_error("IPX router name must be alphanumeric or _"); - return 0; - } - - if (count >= sizeof (ipxcp_wantoptions[0].name)) { - option_error("IPX router name is limited to %d characters", - sizeof (ipxcp_wantoptions[0].name) - 1); - return 0; - } - - dest[count++] = toupper (ch); - } - - return 1; -} - -static int -setipxcptimeout (argv) - char **argv; -{ - return int_option(*argv, &ipxcp_fsm[0].timeouttime); -} - -static int -setipxcpterm (argv) - char **argv; -{ - return int_option(*argv, &ipxcp_fsm[0].maxtermtransmits); -} - -static int -setipxcpconf (argv) - char **argv; -{ - return int_option(*argv, &ipxcp_fsm[0].maxconfreqtransmits); -} - -static int -setipxcpfails (argv) - char **argv; -{ - return int_option(*argv, &ipxcp_fsm[0].maxnakloops); -} - -static int -setipxnetwork(argv) - char **argv; -{ - u_int32_t v; - - if (!number_option(*argv, &v, 16)) - return 0; - - ipxcp_wantoptions[0].our_network = (int) v; - ipxcp_wantoptions[0].neg_nn = 1; - return 1; -} - -static int -setipxanet(argv) - char **argv; -{ - ipxcp_wantoptions[0].accept_network = 1; - ipxcp_allowoptions[0].accept_network = 1; - return 1; -} - -static int -setipxalcl(argv) - char **argv; -{ - ipxcp_wantoptions[0].accept_local = 1; - ipxcp_allowoptions[0].accept_local = 1; - return 1; -} - -static int -setipxarmt(argv) - char **argv; -{ - ipxcp_wantoptions[0].accept_remote = 1; - ipxcp_allowoptions[0].accept_remote = 1; - return 1; -} - -static u_char * -setipxnodevalue(src,dst) -u_char *src, *dst; -{ - int indx; - int item; - - for (;;) { - if (!isxdigit (*src)) - break; - - for (indx = 0; indx < 5; ++indx) { - dst[indx] <<= 4; - dst[indx] |= (dst[indx + 1] >> 4) & 0x0F; - } - - item = toupper (*src) - '0'; - if (item > 9) - item -= 7; - - dst[5] = (dst[5] << 4) | item; - ++src; - } - return src; -} - -static int -setipxnode(argv) - char **argv; -{ - char *end; - - memset (&ipxcp_wantoptions[0].our_node[0], 0, 6); - memset (&ipxcp_wantoptions[0].his_node[0], 0, 6); - - end = setipxnodevalue (*argv, &ipxcp_wantoptions[0].our_node[0]); - if (*end == ':') - end = setipxnodevalue (++end, &ipxcp_wantoptions[0].his_node[0]); - - if (*end == '\0') { - ipxcp_wantoptions[0].neg_node = 1; - return 1; - } - - option_error("invalid parameter '%s' for ipx-node option", *argv); - return 0; -} - -static int -setipxproto(argv) - char **argv; -{ - ipxcp_protent.enabled_flag = 1; - return 1; -} - -static int -resetipxproto(argv) - char **argv; -{ - ipxcp_protent.enabled_flag = 0; - return 1; -} -#else - -static int -resetipxproto(argv) - char **argv; -{ - return 1; -} -#endif /* IPX_CHANGE */ - -#ifdef MSLANMAN -static int -setmslanman(argv) - char **argv; -{ - ms_lanman = 1; - return (1); -} -#endif diff --git a/usr.sbin/pppd/patchlevel.h b/usr.sbin/pppd/patchlevel.h deleted file mode 100644 index bc49c58..0000000 --- a/usr.sbin/pppd/patchlevel.h +++ /dev/null @@ -1,6 +0,0 @@ -/* $FreeBSD$ */ -#define PATCHLEVEL 5 - -#define VERSION "2.3" -#define IMPLEMENTATION "" -#define DATE "4 May 1998" diff --git a/usr.sbin/pppd/pathnames.h b/usr.sbin/pppd/pathnames.h deleted file mode 100644 index 5d09b0b..0000000 --- a/usr.sbin/pppd/pathnames.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * define path names - * - * $FreeBSD$ - */ - -#ifdef HAVE_PATHS_H -#include <paths.h> - -#else -#define _PATH_VARRUN "/etc/ppp/" -#define _PATH_DEVNULL "/dev/null" -#endif - -#define _PATH_UPAPFILE "/etc/ppp/pap-secrets" -#define _PATH_CHAPFILE "/etc/ppp/chap-secrets" -#define _PATH_SYSOPTIONS "/etc/ppp/options" -#define _PATH_IPUP "/etc/ppp/ip-up" -#define _PATH_IPDOWN "/etc/ppp/ip-down" -#define _PATH_AUTHUP "/etc/ppp/auth-up" -#define _PATH_AUTHDOWN "/etc/ppp/auth-down" -#define _PATH_TTYOPT "/etc/ppp/options." -#define _PATH_CONNERRS "/var/log/connect-errors" -#define _PATH_USEROPT ".ppprc" -#define _PATH_PEERFILES "/etc/ppp/peers/" -#define _PATH_PPPDENY "/etc/ppp/ppp.deny" -#define _PATH_PPPSHELLS "/etc/ppp/ppp.shells" - -#ifdef INET6 -#define _PATH_IPV6UP "/etc/ppp/ipv6-up" -#define _PATH_IPV6DOWN "/etc/ppp/ipv6-down" -#endif - -#ifdef IPX_CHANGE -#define _PATH_IPXUP "/etc/ppp/ipx-up" -#define _PATH_IPXDOWN "/etc/ppp/ipx-down" -#endif /* IPX_CHANGE */ diff --git a/usr.sbin/pppd/pppd.8 b/usr.sbin/pppd/pppd.8 deleted file mode 100644 index ba55f21..0000000 --- a/usr.sbin/pppd/pppd.8 +++ /dev/null @@ -1,1247 +0,0 @@ -.\" manual page [] for pppd 2.3 -.\" $FreeBSD$ -.\" SH section heading -.\" SS subsection heading -.\" LP paragraph -.\" IP indented paragraph -.\" TP hanging label -.TH PPPD 8 -.SH NAME -pppd \- Point to Point Protocol daemon -.SH SYNOPSIS -.B pppd -[ -.I tty_name -] [ -.I speed -] [ -.I options -] -.SH DESCRIPTION -.LP -The Point-to-Point Protocol (PPP) provides a method for transmitting -datagrams over serial point-to-point links. PPP -is composed of three parts: a method for encapsulating datagrams over -serial links, an extensible Link Control Protocol (LCP), and -a family of Network Control Protocols (NCP) for establishing -and configuring different network-layer protocols. -.LP -The encapsulation scheme is provided by driver code in the kernel. -Pppd provides the basic LCP, authentication support, and an NCP for -establishing and configuring the Internet Protocol (IP) (called the IP -Control Protocol, IPCP). -.SH FREQUENTLY USED OPTIONS -.TP -.I <tty_name> -Communicate over the named device. The string "/dev/" is prepended if -necessary. If no device name is given, or if the name of the terminal -connected to the standard input is given, pppd -will use that terminal, and will not fork to put itself in the -background. This option is privileged if the \fInoauth\fR option is -used. -.TP -.I <speed> -Set the baud rate to <speed> (a decimal number). On systems such as -4.4BSD and NetBSD, any speed can be specified, providing that it is -supported by the serial device driver. Other systems -(e.g. SunOS, Linux) allow only a limited set of speeds. -.TP -.B active-filter \fIfilter-expression -Specifies a packet filter to be applied to data packets to determine -which packets are to be regarded as link activity, and therefore reset -the idle timer, or cause the link to be brought up in demand-dialling -mode. This option is useful in conjunction with the -\fBidle\fR option if there are packets being sent or received -regularly over the link (for example, routing information packets) -which would otherwise prevent the link from ever appearing to be idle. -The \fIfilter-expression\fR syntax is as described for tcpdump(1), -except that qualifiers which are inappropriate for a PPP link, such as -\fBether\fR and \fBarp\fR, are not permitted. Generally the filter -expression should be enclosed in single-quotes to prevent whitespace -in the expression from being interpreted by the shell. -This option -only available -if both the kernel and pppd were compiled with PPP_FILTER defined. -.TP -.B asyncmap \fI<map> -Set the async character map to <map>. This map describes which -control characters cannot be successfully received over the serial -line. Pppd will ask the peer to send these characters as a 2-byte -escape sequence. The argument is a 32 bit hex number with each bit -representing a character to escape. Bit 0 (00000001) represents the -character 0x00; bit 31 (80000000) represents the character 0x1f or ^_. -If multiple \fIasyncmap\fR options are given, the values are ORed -together. If no \fIasyncmap\fR option is given, no async character -map will be negotiated for the receive direction; the peer should then -escape \fIall\fR control characters. To escape transmitted -characters, use the \fIescape\fR option. -.TP -.B auth -Require the peer to authenticate itself before allowing network -packets to be sent or received. -.TP -.B call \fIname -Read options from the file /etc/ppp/peers/\fIname\fR. This file may -contain privileged options, such as \fInoauth\fR, even if pppd -is not being run by root. The \fIname\fR string may not begin with / -or include .. as a pathname component. The format of the options file -is described below. -.TP -.B connect \fIscript -Use the executable or shell command specified by \fIscript\fR to set -up the serial line. This script would typically use the chat(8) -program to dial the modem and start the remote ppp session. This -option is privileged if the \fInoauth\fR option is used. -.TP -.B connect-max-attempts \fI<n> -Attempt dial-out connection to remote system no more than specified number -of times (default = 1). If the connection is not made, pppd will exit. -Requires that \fBpersist\fR has been specified. -.TP -.B crtscts -Use hardware flow control (i.e. RTS/CTS) to control the flow of data -on the serial port. If neither the \fIcrtscts\fR nor the -\fInocrtscts\fR option is given, the hardware flow control setting -for the serial port is left unchanged. -.TP -.B defaultroute -Add a default route to the system routing tables, using the peer as -the gateway, when IPCP negotiation is successfully completed. -This entry is removed when the PPP connection is broken. This option -is privileged if the \fInodefaultroute\fR option has been specified. -.TP -.B disconnect \fIscript -Run the executable or shell command specified by \fIscript\fR after -pppd has terminated the link. This script could, for example, issue -commands to the modem to cause it to hang up if hardware modem control -signals were not available. The disconnect script is not run if the -modem has already hung up. This option is privileged if the -\fInoauth\fR option is used. -.TP -.B escape \fIxx,yy,... -Specifies that certain characters should be escaped on transmission -(regardless of whether the peer requests them to be escaped with its -async control character map). The characters to be escaped are -specified as a list of hex numbers separated by commas. Note that -almost any character can be specified for the \fIescape\fR option, -unlike the \fIasyncmap\fR option which only allows control characters -to be specified. The characters which may not be escaped are those -with hex values 0x20 - 0x3f or 0x5e. -.TP -.B file \fIname -Read options from file \fIname\fR (the format is described below). -The file must be readable by the user who has invoked pppd. -.TP -.B lock -Specifies that pppd should create a UUCP-style lock file for the -serial device to ensure exclusive access to the device. -.TP -.B mru \fIn -Set the MRU [Maximum Receive Unit] value to \fIn\fR. -Pppd -will ask the peer to send packets of no more than \fIn\fR bytes. The -minimum MRU value is 128. The default MRU value is 1500. A value of -296 is recommended for slow links (40 bytes for TCP/IP header + 256 -bytes of data). (Note that for IPv6 MRU must be at least 1280) -.TP -.B mtu \fIn -Set the MTU [Maximum Transmit Unit] value to \fIn\fR. Unless the -peer requests a smaller value via MRU negotiation, pppd will -request that the kernel networking code send data packets of no more -than \fIn\fR bytes through the PPP network interface. (Note that for -IPv6 MTU must be at least 1280) -.TP -.B passive -Enables the "passive" option in the LCP. With this option, pppd will -attempt to initiate a connection; if no reply is received from the -peer, pppd will then just wait passively for a valid LCP packet from -the peer, instead of exiting, as it would without this option. -.SH OPTIONS -.TP -.I <local_IP_address>\fB:\fI<remote_IP_address> -Set the local and/or remote interface IP addresses. Either one may be -omitted. The IP addresses can be specified with a host name or in -decimal dot notation (e.g. 150.234.56.78). The default local -address is the (first) IP address of the system (unless the -\fInoipdefault\fR -option is given). The remote address will be obtained from the peer -if not specified in any option. Thus, in simple cases, this option is -not required. If a local and/or remote IP address is specified with -this option, pppd -will not accept a different value from the peer in the IPCP -negotiation, unless the \fIipcp-accept-local\fR and/or -\fIipcp-accept-remote\fR options are given, respectively. -.TP -.B ipv6 \fI<local_interface_identifier>\fR,\fI<remote_interface_identifier> -Set the local and/or remote 64-bit interface identifier. Either one may be -omitted. The identifier must be specified in standard ascii notation of -IPv6 addresses (e.g. ::dead:beef). If the -\fIipv6cp-use-ipaddr\fR -option is given, the local identifier is the local IPv4 address (see above). -On systems which supports a unique persistent id, such as EUI-48 derived -from the Ethernet MAC address, \fIipv6cp-use-persistent\fR option can be -used to replace the \fIipv6 <local>,<remote>\fR option. Otherwise the -identifier is randomized. -.TP -.B bsdcomp \fInr,nt -Request that the peer compress packets that it sends, using the -BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and -agree to compress packets sent to the peer with a maximum code size of -\fInt\fR bits. If \fInt\fR is not specified, it defaults to the value -given for \fInr\fR. Values in the range 9 to 15 may be used for -\fInr\fR and \fInt\fR; larger values give better compression but -consume more kernel memory for compression dictionaries. -Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables -compression in the corresponding direction. Use \fInobsdcomp\fR or -\fIbsdcomp 0\fR to disable BSD-Compress compression entirely. -.TP -.B callback \fIphone_number -Request a call-back to the \fIphone_number\fR. This only works if the peer -is speaking the Call Back Configuration Protocol. Do not put this into the -main options file if you sometimes connect to servers that don't support -it. -.TP -.B chap-interval \fIn -If this option is given, pppd will rechallenge the peer every \fIn\fR -seconds. -.TP -.B chap-max-challenge \fIn -Set the maximum number of CHAP challenge transmissions to \fIn\fR -(default 10). -.TP -.B chap-restart \fIn -Set the CHAP restart interval (retransmission timeout for challenges) -to \fIn\fR seconds (default 3). -.TP -.B debug -Enables connection debugging facilities. -If this option is given, pppd will log the contents of all -control packets sent or received in a readable form. The packets are -logged through syslog with facility \fIdaemon\fR and level -\fIdebug\fR. This information can be directed to a file by setting up -/etc/syslog.conf appropriately (see syslog.conf(5)). -.TP -.B default-asyncmap -Disable asyncmap negotiation, forcing all control characters to be -escaped for both the transmit and the receive direction. -.TP -.B default-mru -Disable MRU [Maximum Receive Unit] negotiation. With this option, -pppd will use the default MRU value of 1500 bytes for both the -transmit and receive direction. -.TP -.B deflate \fInr,nt -Request that the peer compress packets that it sends, using the -Deflate scheme, with a maximum window size of \fI2**nr\fR bytes, and -agree to compress packets sent to the peer with a maximum window size -of \fI2**nt\fR bytes. If \fInt\fR is not specified, it defaults to -the value given for \fInr\fR. Values in the range 8 to 15 may be used -for \fInr\fR and \fInt\fR; larger values give better compression but -consume more kernel memory for compression dictionaries. -Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables -compression in the corresponding direction. Use \fInodeflate\fR or -\fIdeflate 0\fR to disable Deflate compression entirely. (Note: pppd -requests Deflate compression in preference to BSD-Compress if the peer -can do either.) -.TP -.B demand -Initiate the link only on demand, i.e. when data traffic is present. -With this option, the remote IP address must be specified by the user -on the command line or in an options file. Pppd will initially -configure the interface and enable it for IP traffic without -connecting to the peer. When traffic is available, pppd will -connect to the peer and perform negotiation, authentication, etc. -When this is completed, pppd will commence passing data packets -(i.e., IP packets) across the link. - -The \fIdemand\fR option implies the \fIpersist\fR option. If this -behaviour is not desired, use the \fInopersist\fR option after the -\fIdemand\fR option. The \fIidle\fR and \fIholdoff\fR -options are also useful in conjunction with the \fIdemand\fR option. -.TP -.B domain \fId -Append the domain name \fId\fR to the local host name for authentication -purposes. For example, if gethostname() returns the name porsche, but -the fully qualified domain name is porsche.Quotron.COM, you could -specify \fIdomain Quotron.COM\fR. Pppd would then use the name -\fIporsche.Quotron.COM\fR for looking up secrets in the secrets file, -and as the default name to send to the peer when authenticating itself -to the peer. This option is privileged. -.TP -.B holdoff \fIn -Specifies how many seconds to wait before re-initiating the link after -it terminates. This option only has any effect if the \fIpersist\fR -or \fIdemand\fR option is used. The holdoff period is not applied if -the link was terminated because it was idle. -.TP -.B idle \fIn -Specifies that pppd should disconnect if the link is idle for \fIn\fR -seconds. The link is idle when no data packets (i.e. IP packets) are -being sent or received. Note: it is not advisable to use this option -with the \fIpersist\fR option without the \fIdemand\fR option. -If the \fBactive-filter\fR -option is given, data packets which are rejected by the specified -activity filter also count as the link being idle. -.TP -.B ipcp-accept-local -With this option, pppd will accept the peer's idea of our local IP -address, even if the local IP address was specified in an option. -.TP -.B ipcp-accept-remote -With this option, pppd will accept the peer's idea of its (remote) IP -address, even if the remote IP address was specified in an option. -.TP -.B ipcp-max-configure \fIn -Set the maximum number of IPCP configure-request transmissions to -\fIn\fR (default 10). -.TP -.B ipcp-max-failure \fIn -Set the maximum number of IPCP configure-NAKs returned before starting -to send configure-Rejects instead to \fIn\fR (default 10). -.TP -.B ipcp-max-terminate \fIn -Set the maximum number of IPCP terminate-request transmissions to -\fIn\fR (default 3). -.TP -.B ipcp-restart \fIn -Set the IPCP restart interval (retransmission timeout) to \fIn\fR -seconds (default 3). -.TP -.B ipparam \fIstring -Provides an extra parameter to the ip-up and ip-down scripts. If this -option is given, the \fIstring\fR supplied is given as the 6th -parameter to those scripts. -.TP -.B ipv6cp-max-configure \fIn -Set the maximum number of IPv6CP configure-request transmissions to -\fIn\fR (default 10). -.TP -.B ipv6cp-max-failure \fIn -Set the maximum number of IPv6CP configure-NAKs returned before starting -to send configure-Rejects instead to \fIn\fR (default 10). -.TP -.B ipv6cp-max-terminate \fIn -Set the maximum number of IPv6CP terminate-request transmissions to -\fIn\fR (default 3). -.TP -.B ipv6cp-restart \fIn -Set the IPv6CP restart interval (retransmission timeout) to \fIn\fR -seconds (default 3). -.TP -.B ipx -Enable the IPXCP and IPX protocols. This option is presently only -supported under Linux, and only if your kernel has been configured to -include IPX support. -.TP -.B ipx-network \fIn -Set the IPX network number in the IPXCP configure request frame to -\fIn\fR, a hexadecimal number (without a leading 0x). There is no -valid default. If this option is not specified, the network number is -obtained from the peer. If the peer does not have the network number, -the IPX protocol will not be started. -.TP -.B ipx-node \fIn\fB:\fIm -Set the IPX node numbers. -The two node numbers are separated from each -other with a colon character. -The first number \fIn\fR is the local -node number. -The second number \fIm\fR is the peer's node number. -Each -node number is a hexadecimal number, at most 10 digits long. -The node -numbers on the ipx-network must be unique. -There is no valid -default. -If this option is not specified then the node numbers are -obtained from the peer. -.TP -.B ipx-router-name \fI<string> -Set the name of the router. -This is a string and is sent to the peer -as information data. -.TP -.B ipx-routing \fIn -Set the routing protocol to be received by this option. -More than one -instance of \fIipx-routing\fR may be specified. -The '\fInone\fR' -option (0) may be specified as the only instance of ipx-routing. -The -values may be \fI0\fR for \fINONE\fR, \fI2\fR for \fIRIP/SAP\fR, and -\fI4\fR for \fINLSP\fR. -.TP -.B ipxcp-accept-local -Accept the peer's NAK for the node number specified in the ipx-node -option. -If a node number was specified, and non-zero, the default is -to insist that the value be used. -If you include this option then you -will permit the peer to override the entry of the node number. -.TP -.B ipxcp-accept-network -Accept the peer's NAK for the network number specified in the -ipx-network option. -If a network number was specified, and non-zero, the -default is to insist that the value be used. -If you include this -option then you will permit the peer to override the entry of the node -number. -.TP -.B ipxcp-accept-remote -Use the peer's network number specified in the configure request -frame. -If a node number was specified for the peer and this option was -not specified, the peer will be forced to use the value which you have -specified. -.TP -.B ipxcp-max-configure \fIn -Set the maximum number of IPXCP configure request frames which the -system will send to \fIn\fR. -The default is 10. -.TP -.B ipxcp-max-failure \fIn -Set the maximum number of IPXCP NAK frames which the local system will -send before it rejects the options. -The default value is 3. -.TP -.B ipxcp-max-terminate \fIn -Set the maximum number of IPXCP terminate request frames before the -local system considers that the peer is not listening to them. -The -default value is 3. -.TP -.B kdebug \fIn -Enable debugging code in the kernel-level PPP driver. The argument -\fIn\fR is a number which is the sum of the following values: 1 to -enable general debug messages, 2 to request that the contents of -received packets be printed, and 4 to request that the contents of -transmitted packets be printed. On most systems, messages printed by -the kernel are logged by syslog(1) to a file as directed in the -/etc/syslog.conf configuration file. -.TP -.B lcp-echo-failure \fIn -If this option is given, pppd will presume the peer to be dead -if \fIn\fR LCP echo-requests are sent without receiving a valid LCP -echo-reply. If this happens, pppd will terminate the -connection. Use of this option requires a non-zero value for the -\fIlcp-echo-interval\fR parameter. This option can be used to enable -pppd to terminate after the physical connection has been broken -(e.g., the modem has hung up) in situations where no hardware modem -control lines are available. -.TP -.B lcp-echo-interval \fIn -If this option is given, pppd will send an LCP echo-request frame to -the peer every \fIn\fR seconds. Normally the peer should respond to -the echo-request by sending an echo-reply. This option can be used -with the \fIlcp-echo-failure\fR option to detect that the peer is no -longer connected. -.TP -.B lcp-max-configure \fIn -Set the maximum number of LCP configure-request transmissions to -\fIn\fR (default 10). -.TP -.B lcp-max-failure \fIn -Set the maximum number of LCP configure-NAKs returned before starting -to send configure-Rejects instead to \fIn\fR (default 10). -.TP -.B lcp-max-terminate \fIn -Set the maximum number of LCP terminate-request transmissions to -\fIn\fR (default 3). -.TP -.B lcp-restart \fIn -Set the LCP restart interval (retransmission timeout) to \fIn\fR -seconds (default 3). -.TP -.B local -Don't use the modem control lines. With this option, pppd will ignore -the state of the CD (Carrier Detect) signal from the modem and will -not change the state of the DTR (Data Terminal Ready) signal. -.TP -.B login -Use the system password database for authenticating the peer using -PAP, and record the user in the system wtmp file. Note that the peer -must have an entry in the /etc/ppp/pap-secrets file as well as the -system password database to be allowed access. -.TP -.B maxconnect \fIn -Terminate the connection when it has been available for network -traffic for \fIn\fR seconds (i.e. \fIn\fR seconds after the first -network control protocol comes up). -.TP -.B modem -Use the modem control lines. This option is the default. With this -option, pppd will wait for the CD (Carrier Detect) signal from the -modem to be asserted when opening the serial device (unless a connect -script is specified), and it will drop the DTR (Data Terminal Ready) -signal briefly when the connection is terminated and before executing -the connect script. On Ultrix, this option implies hardware flow -control, as for the \fIcrtscts\fR option. -.TP -.B ms-dns \fI<addr> -If pppd is acting as a server for Microsoft Windows clients, this -option allows pppd to supply one or two DNS (Domain Name Server) -addresses to the clients. The first instance of this option specifies -the primary DNS address; the second instance (if given) specifies the -secondary DNS address. (This option was present in some older -versions of pppd under the name \fBdns-addr\fR.) -.TP -.B ms-wins \fI<addr> -If pppd is acting as a server for Microsoft Windows or "Samba" -clients, this option allows pppd to supply one or two WINS (Windows -Internet Name Services) server addresses to the clients. The first -instance of this option specifies the primary WINS address; the second -instance (if given) specifies the secondary WINS address. -.TP -.B name \fIname -Set the name of the local system for authentication purposes to -\fIname\fR. This is a privileged option. With this option, pppd will -use lines in the secrets files which have \fIname\fR as the second -field when looking for a secret to use in authenticating the peer. In -addition, unless overridden with the \fIuser\fR option, \fIname\fR -will be used as the name to send to the peer when authenticating the -local system to the peer. (Note that pppd does not append the domain -name to \fIname\fR.) -.TP -.B netmask \fIn -Set the interface netmask to \fIn\fR, a 32 bit netmask in "decimal dot" -notation (e.g. 255.255.255.0). If this option is given, the value -specified is ORed with the default netmask. The default netmask is -chosen based on the negotiated remote IP address; it is the -appropriate network mask for the class of the remote IP address, ORed -with the netmasks for any non point-to-point network interfaces in the -system which are on the same network. -.TP -.B noaccomp -Disable Address/Control compression in both directions (send and -receive). -.TP -.B noauth -Do not require the peer to authenticate itself. This option is -privileged if the \fIauth\fR option is specified in /etc/ppp/options. -.TP -.B nobsdcomp -Disables BSD-Compress compression; \fBpppd\fR will not request or -agree to compress packets using the BSD-Compress scheme. -.TP -.B noccp -Disable CCP (Compression Control Protocol) negotiation. This option -should only be required if the peer is buggy and gets confused by -requests from pppd for CCP negotiation. -.TP -.B nocrtscts -Disable hardware flow control (i.e. RTS/CTS) on the serial port. If -neither the \fIcrtscts\fR nor the \fInocrtscts\fR option is given, -the hardware flow control setting for the serial port is left -unchanged. -.TP -.B nodefaultroute -Disable the \fIdefaultroute\fR option. The system administrator who -wishes to prevent users from creating default routes with pppd -can do so by placing this option in the /etc/ppp/options file. -.TP -.B nodeflate -Disables Deflate compression; pppd will not request or agree to -compress packets using the Deflate scheme. -.TP -.B nodetach -Don't detach from the controlling terminal. Without this option, if a -serial device other than the terminal on the standard input is -specified, pppd will fork to become a background process. -.TP -.B noip -Disable IPCP negotiation and IP communication. This option should -only be required if the peer is buggy and gets confused by requests -from pppd for IPCP negotiation. -.TP -.B noipv6 -Disable IPv6CP negotiation and IPv6 communication. This option should -only be required if the peer is buggy and gets confused by requests -from pppd for IPv6CP negotiation. -.TP -.B noipdefault -Disables the default behaviour when no local IP address is specified, -which is to determine (if possible) the local IP address from the -hostname. With this option, the peer will have to supply the local IP -address during IPCP negotiation (unless it specified explicitly on the -command line or in an options file). -.TP -.B noipx -Disable the IPXCP and IPX protocols. This option should only be -required if the peer is buggy and gets confused by requests from pppd -for IPXCP negotiation. -.TP -.B nomagic -Disable magic number negotiation. With this option, pppd cannot -detect a looped-back line. This option should only be needed if the -peer is buggy. -.TP -.B nopcomp -Disable protocol field compression negotiation in both the receive and -the transmit direction. -.TP -.B nopersist -Exit once a connection has been made and terminated. This is the -default unless the \fIpersist\fR or \fIdemand\fR option has been -specified. -.TP -.B nopredictor1 -Do not accept or agree to Predictor-1 compression. -.TP -.B noproxyarp -Disable the \fIproxyarp\fR option. The system administrator who -wishes to prevent users from creating proxy ARP entries with pppd can -do so by placing this option in the /etc/ppp/options file. -.TP -.B novj -Disable Van Jacobson style TCP/IP header compression in both the -transmit and the receive direction. -.TP -.B novjccomp -Disable the connection-ID compression option in Van Jacobson style -TCP/IP header compression. With this option, pppd will not omit the -connection-ID byte from Van Jacobson compressed TCP/IP headers, nor -ask the peer to do so. -.TP -.B papcrypt -Indicates that all secrets in the /etc/ppp/pap-secrets file which are -used for checking the identity of the peer are encrypted, and thus -pppd should not accept a password which, before encryption, is -identical to the secret from the /etc/ppp/pap-secrets file. -.TP -.B pap-max-authreq \fIn -Set the maximum number of PAP authenticate-request transmissions to -\fIn\fR (default 10). -.TP -.B pap-restart \fIn -Set the PAP restart interval (retransmission timeout) to \fIn\fR -seconds (default 3). -.TP -.B pap-timeout \fIn -Set the maximum time that pppd will wait for the peer to authenticate -itself with PAP to \fIn\fR seconds (0 means no limit). -.TP -.B pass-filter \fIfilter-expression -Specifies a packet filter to applied to data packets being sent or -received to determine which packets should be allowed to pass. -Packets which are rejected by the filter are silently discarded. This -option can be used to prevent specific network daemons (such as -routed) using up link bandwidth, or to provide a basic firewall -capability. -The \fIfilter-expression\fR syntax is as described for tcpdump(1), -except that qualifiers which are inappropriate for a PPP link, such as -\fBether\fR and \fBarp\fR, are not permitted. Generally the filter -expression should be enclosed in single-quotes to prevent whitespace -in the expression from being interpreted by the shell. Note that it -is possible to apply different constraints to incoming and outgoing -packets using the \fBinbound\fR and \fBoutbound\fR qualifiers. -This -option is currently only available under NetBSD, and then only if both -the kernel and pppd were compiled with PPP_FILTER defined. -.TP -.B persist -Do not exit after a connection is terminated; instead try to reopen -the connection. -.TP -.B predictor1 -Request that the peer compress frames that it sends using Predictor-1 -compression, and agree to compress transmitted frames with Predictor-1 -if requested. This option has no effect unless the kernel driver -supports Predictor-1 compression. -.TP -.B proxyarp -Add an entry to this system's ARP [Address Resolution Protocol] table -with the IP address of the peer and the Ethernet address of this -system. This will have the effect of making the peer appear to other -systems to be on the local ethernet. -.TP -.B remotename \fIname -Set the assumed name of the remote system for authentication purposes -to \fIname\fR. -.TP -.B refuse-chap -With this option, pppd will not agree to authenticate itself to the -peer using CHAP. -.TP -.B refuse-pap -With this option, pppd will not agree to authenticate itself to the -peer using PAP. -.TP -.B require-chap -Require the peer to authenticate itself using CHAP [Challenge -Handshake Authentication Protocol] authentication. -.TP -.B require-pap -Require the peer to authenticate itself using PAP [Password -Authentication Protocol] authentication. -.TP -.B silent -With this option, pppd will not transmit LCP packets to initiate a -connection until a valid LCP packet is received from the peer (as for -the `passive' option with ancient versions of pppd). -.TP -.B usehostname -Enforce the use of the hostname (with domain name appended, if given) -as the name of the local system for authentication purposes (overrides -the \fIname\fR option). -.TP -.B user \fIname -Sets the name used for authenticating the local system to the peer to -\fIname\fR. -.TP -.B vj-max-slots \fIn -Sets the number of connection slots to be used by the Van Jacobson -TCP/IP header compression and decompression code to \fIn\fR, which -must be between 2 and 16 (inclusive). -.TP -.B welcome \fIscript -Run the executable or shell command specified by \fIscript\fR before -initiating PPP negotiation, after the connect script (if any) has -completed. This option is privileged if the \fInoauth\fR option is -used. -.TP -.B xonxoff -Use software flow control (i.e. XON/XOFF) to control the flow of data on -the serial port. -.SH OPTIONS FILES -Options can be taken from files as well as the command line. Pppd -reads options from the files /etc/ppp/options, ~/.ppprc and -/etc/ppp/options.\fIttyname\fR (in that order) before processing the -options on the command line. (In fact, the command-line options are -scanned to find the terminal name before the options.\fIttyname\fR -file is read.) In forming the name of the options.\fIttyname\fR file, -the initial /dev/ is removed from the terminal name, and any remaining -/ characters are replaced with dots. -.PP -An options file is parsed into a series of words, delimited by -whitespace. Whitespace can be included in a word by enclosing the -word in double-quotes ("). A backslash (\\) quotes the following character. -A hash (#) starts a comment, which continues until the end of the -line. There is no restriction on using the \fIfile\fR or \fIcall\fR -options within an options file. -.SH SECURITY -.I pppd -provides system administrators with sufficient access control that PPP -access to a server machine can be provided to legitimate users without -fear of compromising the security of the server or the network it's -on. In part this is provided by the /etc/ppp/options file, where the -administrator can place options to restrict the ways in which pppd can -be used, and in part by the PAP and CHAP secrets files, where the -administrator can restrict the set of IP addresses which individual -users may use. -.PP -The normal way that pppd should be set up is to have the \fIauth\fR -option in the /etc/ppp/options file. (This may become the default in -later releases.) If users wish to use pppd to dial out to a peer -which will refuse to authenticate itself (such as an internet service -provider), the system administrator should create an options file -under /etc/ppp/peers containing the \fInoauth\fR option, the name of -the serial port to use, and the \fIconnect\fR option (if required), -plus any other appropriate options. In this way, pppd can be set up -to allow non-privileged users to make unauthenticated connections only -to trusted peers. -.PP -As indicated above, some security-sensitive options are privileged, -which means that they may not be used by an ordinary non-privileged -user running a setuid-root pppd, either on the command line, in the -user's ~/.ppprc file, or in an options file read using the \fIfile\fR -option. Privileged options may be used in /etc/ppp/options file or in -an options file read using the \fIcall\fR option. If pppd is being -run by the root user, privileged options can be used without -restriction. -.SH AUTHENTICATION -Authentication is the process whereby one peer convinces the other of -its identity. This involves the first peer sending its name to the -other, together with some kind of secret information which could only -come from the genuine authorized user of that name. In such an -exchange, we will call the first peer the "client" and the other the -"server". The client has a name by which it identifies itself to the -server, and the server also has a name by which it identifies itself -to the client. Generally the genuine client shares some secret (or -password) with the server, and authenticates itself by proving that it -knows that secret. Very often, the names used for authentication -correspond to the internet hostnames of the peers, but this is not -essential. -.LP -At present, pppd supports two authentication protocols: the Password -Authentication Protocol (PAP) and the Challenge Handshake -Authentication Protocol (CHAP). PAP involves the client sending its -name and a cleartext password to the server to authenticate itself. -In contrast, the server initiates the CHAP authentication exchange by -sending a challenge to the client (the challenge packet includes the -server's name). The client must respond with a response which -includes its name plus a hash value derived from the shared secret and -the challenge, in order to prove that it knows the secret. -.LP -The PPP protocol, being symmetrical, allows both peers to require the -other to authenticate itself. In that case, two separate and -independent authentication exchanges will occur. The two exchanges -could use different authentication protocols, and in principle, -different names could be used in the two exchanges. -.LP -The default behaviour of pppd is to agree to authenticate if -requested, and to not require authentication from the peer. However, -pppd will not agree to authenticate itself with a particular protocol -if it has no secrets which could be used to do so. -.LP -Pppd stores secrets for use in authentication in secrets -files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP). -Both secrets files have the same format. The secrets files can -contain secrets for pppd to use in authenticating itself to other -systems, as well as secrets for pppd to use when authenticating other -systems to itself. -.LP -Each line in a secrets file contains one secret. A given secret is -specific to a particular combination of client and server - it can -only be used by that client to authenticate itself to that server. -Thus each line in a secrets file has at least 3 fields: the name of -the client, the name of the server, and the secret. These fields may -be followed by a list of the IP addresses that the specified client -may use when connecting to the specified server. -.LP -A secrets file is parsed into words as for an options file, so the -client name, server name and secrets fields must each be one word, -with any embedded spaces or other special characters quoted or -escaped. Any following words on the same line are taken to be a list -of acceptable IP addresses for that client, or an -override for "local:remote" addresses (the same format used on the -command line or in the options file) when on a line that contains a -specific client name (not a wildcard nor empty). -If there are only 3 words -on the line, or if the first word is "-", then all IP addresses are -disallowed. To allow any address, use "*". -A word starting with "!" indicates that the -specified address is \fInot\fR acceptable. An address may be followed -by "/" and a number \fIn\fR, to indicate a whole subnet, i.e. all -addresses which have the same value in the most significant \fIn\fR -bits. Note that case is significant in the client and server names -and in the secret. -.LP -If the secret starts with an `@', what follows is assumed to be the -name of a file from which to read the secret. A "*" as the client or -server name matches any name. When selecting a secret, pppd takes the -best match, i.e. the match with the fewest wildcards. -.LP -Thus a secrets file contains both secrets for use in authenticating -other hosts, plus secrets which we use for authenticating ourselves to -others. When pppd is authenticating the peer (checking the peer's -identity), it chooses a secret with the peer's name in the first -field and the name of the local system in the second field. The -name of the local system defaults to the hostname, with the domain -name appended if the \fIdomain\fR option is used. This default can be -overridden with the \fIname\fR option, except when the -\fIusehostname\fR option is used. -.LP -When pppd is choosing a secret to use in authenticating itself to the -peer, it first determines what name it is going to use to identify -itself to the peer. This name can be specified by the user with the -\fIuser\fR option. If this option is not used, the name defaults to -the name of the local system, determined as described in the previous -paragraph. Then pppd looks for a secret with this name in the first -field and the peer's name in the second field. Pppd will know the -name of the peer if CHAP authentication is being used, because the -peer will have sent it in the challenge packet. However, if PAP is being -used, pppd will have to determine the peer's name from the options -specified by the user. The user can specify the peer's name directly -with the \fIremotename\fR option. Otherwise, if the remote IP address -was specified by a name (rather than in numeric form), that name will -be used as the peer's name. Failing that, pppd will use the null -string as the peer's name. -.LP -When authenticating the peer with PAP, the supplied password is first -compared with the secret from the secrets file. If the password -doesn't match the secret, the password is encrypted using crypt() and -checked against the secret again. Thus secrets for authenticating the -peer can be stored in encrypted form if desired. If the -\fIpapcrypt\fR option is given, the first (unencrypted) comparison is -omitted, for better security. -.LP -Furthermore, if the \fIlogin\fR option was specified, the username and -password are also checked against the system password database. Thus, -the system administrator can set up the pap-secrets file to allow PPP -access only to certain users, and to restrict the set of IP addresses -that each user can use. Typically, when using the \fIlogin\fR option, -the secret in /etc/ppp/pap-secrets would be "", which will match any -password supplied by the peer. This avoids the need to have the same -secret in two places. -.LP -Additional checks are performed when the \fBlogin\fR option is used. -If the file /etc/ppp/ppp.deny exists, and the user is listed in it, -the authentication fails. If the file /etc/ppp/ppp.shells exists and -the user's normal login shell is not listed, the authentication fails. -.LP -Authentication must be satisfactorily completed before IPCP (or any -other Network Control Protocol) can be started. If the peer is -required to authenticate itself, and fails to do so, pppd will -terminated the link (by closing LCP). If IPCP negotiates an -unacceptable IP address for the remote host, IPCP will be closed. IP -packets can only be sent or received when IPCP is open. -.LP -In some cases it is desirable to allow some hosts which can't -authenticate themselves to connect and use one of a restricted set of -IP addresses, even when the local host generally requires -authentication. If the peer refuses to authenticate itself when -requested, pppd takes that as equivalent to authenticating with PAP -using the empty string for the username and password. Thus, by adding -a line to the pap-secrets file which specifies the empty string for -the client and password, it is possible to allow restricted access to -hosts which refuse to authenticate themselves. -.SH ROUTING -.LP -When IPCP negotiation is completed successfully, pppd will inform the -kernel of the local and remote IP addresses for the ppp interface. -This is sufficient to create a host route to the remote end of the -link, which will enable the peers to exchange IP packets. -Communication with other machines generally requires further -modification to routing tables and/or ARP (Address Resolution -Protocol) tables. In most cases the \fIdefaultroute\fR and/or -\fIproxyarp\fR options are sufficient for this, but in some cases -further intervention is required. The /etc/ppp/ip-up script can be -used for this. -.LP -Sometimes it is desirable to add a default route through the remote -host, as in the case of a machine whose only connection to the -Internet is through the ppp interface. The \fIdefaultroute\fR option -causes pppd to create such a default route when IPCP comes up, and -delete it when the link is terminated. -.LP -In some cases it is desirable to use proxy ARP, for example on a -server machine connected to a LAN, in order to allow other hosts to -communicate with the remote host. The \fIproxyarp\fR option causes -pppd to look for a network interface on the same subnet as the remote -host (an interface supporting broadcast and ARP, which is up and not a -point-to-point or loopback interface). If found, pppd creates a -permanent, published ARP entry with the IP address of the remote host -and the hardware address of the network interface found. -.LP -When the \fIdemand\fR option is used, the interface IP addresses have -already been set at the point when IPCP comes up. If pppd has not -been able to negotiate the same addresses that it used to configure -the interface (for example when the peer is an ISP that uses dynamic -IP address assignment), pppd has to change the interface IP addresses -to the negotiated addresses. This may disrupt existing connections, -and the use of demand dialling with peers that do dynamic IP address -assignment is not recommended. -.SH EXAMPLES -.LP -The following examples assume that the /etc/ppp/options file contains -the \fIauth\fR option (as in the default /etc/ppp/options file in the -ppp distribution). -.LP -Probably the most common use of pppd is to dial out to an ISP. This -can be done with a command such as -.IP -pppd call isp -.LP -where the /etc/ppp/peers/isp file is set up by the system -administrator to contain something like this: -.IP -ttyS0 19200 crtscts -.br -connect '/usr/sbin/chat -v -f /etc/ppp/chat-isp' -.br -noauth -.LP -In this example, we are using chat to dial the ISP's modem and go -through any logon sequence required. The /etc/ppp/chat-isp file -contains the script used by chat; it could for example contain -something like this: -.IP -ABORT "NO CARRIER" -.br -ABORT "NO DIALTONE" -.br -ABORT "ERROR" -.br -ABORT "NO ANSWER" -.br -ABORT "BUSY" -.br -ABORT "Username/Password Incorrect" -.br -"" "at" -.br -OK "at&d0&c1" -.br -OK "atdt2468135" -.br -"name:" "^Umyuserid" -.br -"word:" "\\qmypassword" -.br -"ispts" "\\q^Uppp" -.br -"~-^Uppp-~" -.LP -See the chat(8) man page for details of chat scripts. -.LP -Pppd can also be used to provide a dial-in ppp service for users. If -the users already have login accounts, the simplest way to set up the -ppp service is to let the users log in to their accounts and run pppd -(installed setuid-root) with a command such as -.IP -pppd proxyarp -.LP -To allow a user to use the PPP facilities, you need to allocate an IP -address for that user's machine and create an entry in -/etc/ppp/pap-secrets or /etc/ppp/chap-secrets (depending on which -authentication method the PPP implementation on the user's machine -supports), so that the user's -machine can authenticate itself. For example, if Joe has a machine -called "joespc" which is to be allowed to dial in to the machine -called "server" and use the IP address joespc.my.net, you would add an -entry like this to /etc/ppp/pap-secrets or /etc/ppp/chap-secrets: -.IP -joespc server "joe's secret" joespc.my.net -.LP -Alternatively, you can create a username called (for example) "ppp", -whose login shell is pppd and whose home directory is /etc/ppp. -Options to be used when pppd is run this way can be put in -/etc/ppp/.ppprc. -.LP -If your serial connection is any more complicated than a piece of -wire, you may need to arrange for some control characters to be -escaped. In particular, it is often useful to escape XON (^Q) and -XOFF (^S), using \fIasyncmap a0000\fR. If the path includes a telnet, -you probably should escape ^] as well (\fIasyncmap 200a0000\fR). If -the path includes an rlogin, you will need to use the \fIescape ff\fR -option on the end which is running the rlogin client, since many -rlogin implementations are not transparent; they will remove the -sequence [0xff, 0xff, 0x73, 0x73, followed by any 8 bytes] from the -stream. -.SH DIAGNOSTICS -.LP -Messages are sent to the syslog daemon using facility LOG_DAEMON. -(This can be overriden by recompiling pppd with the macro -LOG_PPP defined as the desired facility.) In order to see the error -and debug messages, you will need to edit your /etc/syslog.conf file -to direct the messages to the desired output device or file. -.LP -The \fIdebug\fR option causes the contents of all control packets sent -or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets. -This can be useful if the PPP negotiation does not succeed or if -authentication fails. -If debugging is enabled at compile time, the \fIdebug\fR option also -causes other debugging messages to be logged. -.LP -Debugging can also be enabled or disabled by sending a SIGUSR1 signal -to the pppd process. This signal acts as a toggle. -.SH SCRIPTS -Pppd invokes scripts at various stages in its processing which can be -used to perform site-specific ancillary processing. These scripts are -usually shell scripts, but could be executable code files instead. -Pppd does not wait for the scripts to finish. The scripts are -executed as root (with the real and effective user-id set to 0), so -that they can do things such as update routing tables or run -privileged daemons. Be careful that the contents of these scripts do -not compromise your system's security. Pppd runs the scripts with -standard input, output and error redirected to /dev/null, and with an -environment that is empty except for some environment variables that -give information about the link. The environment variables that pppd -sets are: -.TP -.B DEVICE -The name of the serial tty device being used. -.TP -.B IFNAME -The name of the network interface being used. -.TP -.B IPLOCAL -The IP address for the local end of the link. This is only set when -IPCP has come up. -.TP -.B IPREMOTE -The IP address for the remote end of the link. This is only set when -IPCP has come up. -.TP -.B PEERNAME -The authenticated name of the peer. This is only set if the peer -authenticates itself. -.TP -.B SPEED -The baud rate of the tty device. -.TP -.B UID -The real user-id of the user who invoked pppd. -.P -Pppd invokes the following scripts, if they exist. It is not an error -if they don't exist. -.TP -.B /etc/ppp/auth-up -A program or script which is executed after the remote system -successfully authenticates itself. It is executed with the parameters -.IP -\fIinterface-name peer-name user-name tty-device speed\fR -.IP -Note that this script is not executed if the peer doesn't authenticate -itself, for example when the \fInoauth\fR option is used. -.TP -.B /etc/ppp/auth-down -A program or script which is executed when the link goes down, if -/etc/ppp/auth-up was previously executed. It is executed in the same -manner with the same parameters as /etc/ppp/auth-up. -.TP -.B /etc/ppp/ip-up -A program or script which is executed when the link is available for -sending and receiving IP packets (that is, IPCP has come up). It is -executed with the parameters -.IP -\fIinterface-name tty-device speed local-IP-address -remote-IP-address ipparam\fR -.TP -.B /etc/ppp/ip-down -A program or script which is executed when the link is no longer -available for sending and receiving IP packets. This script can be -used for undoing the effects of the /etc/ppp/ip-up script. It is -invoked in the same manner and with the same parameters as the ip-up -script. -.TP -.B /etc/ppp/ipv6-up -Like /etc/ppp/ip-up, except that it is executed when the link is available -for sending and receiving IPv6 packets. It is executed with the parameters -.IP -\fIinterface-name tty-device speed local-link-local-address -remote-link-local-address ipparam\fR -.TP -.B /etc/ppp/ipv6-down -Similar to /etc/ppp/ip-down, but it is executed when IPv6 packets can no -longer be transmitted on the link. It is executed with the same parameters -as the ipv6-up script. -.TP -.B /etc/ppp/ipx-up -A program or script which is executed when the link is available for -sending and receiving IPX packets (that is, IPXCP has come up). It is -executed with the parameters -.IP -\fIinterface-name tty-device speed network-number local-IPX-node-address -remote-IPX-node-address local-IPX-routing-protocol remote-IPX-routing-protocol -local-IPX-router-name remote-IPX-router-name ipparam pppd-pid\fR -.IP -The local-IPX-routing-protocol and remote-IPX-routing-protocol field -may be one of the following: -.IP -NONE to indicate that there is no routing protocol -.br -RIP to indicate that RIP/SAP should be used -.br -NLSP to indicate that Novell NLSP should be used -.br -RIP NLSP to indicate that both RIP/SAP and NLSP should be used -.TP -.B /etc/ppp/ipx-down -A program or script which is executed when the link is no longer -available for sending and receiving IPX packets. This script can be -used for undoing the effects of the /etc/ppp/ipx-up script. It is -invoked in the same manner and with the same parameters as the ipx-up -script. -.SH FILES -.TP -.B /var/run/ppp\fIn\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp\fIn\fB.pid \fR(others) -Process-ID for pppd process on ppp interface unit \fIn\fR. -.TP -.B /etc/ppp/pap-secrets -Usernames, passwords and IP addresses for PAP authentication. This -file should be owned by root and not readable or writable by any other -user. Pppd will log a warning if this is not the case. -.TP -.B /etc/ppp/chap-secrets -Names, secrets and IP addresses for CHAP authentication. As for -/etc/ppp/pap-secrets, this file should be owned by root and not -readable or writable by any other user. Pppd will log a warning if -this is not the case. -.TP -.B /etc/ppp/options -System default options for pppd, read before user default options or -command-line options. -.TP -.B ~/.ppprc -User default options, read before /etc/ppp/options.\fIttyname\fR. -.TP -.B /etc/ppp/options.\fIttyname -System default options for the serial port being used, read after -~/.ppprc. In forming the \fIttyname\fR part of this -filename, an initial /dev/ is stripped from the port name (if -present), and any slashes in the remaining part are converted to -dots. -.TP -.B /etc/ppp/peers -A directory containing options files which may contain privileged -options, even if pppd was invoked by a user other than root. The -system administrator can create options files in this directory to -permit non-privileged users to dial out without requiring the peer to -authenticate, but only to certain trusted peers. -.TP -.B /etc/ppp/ppp.deny -Lists users who may not use the system password PAP authentication. -.TP -.B /etc/ppp/ppp.shells -Lists user shells which are approved for system password PAP authentication -logins. -.TP -.B /usr/share/examples/pppd/ -Sample pppd configuration files. -.SH SEE ALSO -.IR chat(8), -.IR ppp(8) -.TP -.B RFC1144 -Jacobson, V. -\fICompressing TCP/IP headers for low-speed serial links.\fR -February 1990. -.TP -.B RFC1321 -Rivest, R. -.I The MD5 Message-Digest Algorithm. -April 1992. -.TP -.B RFC1332 -McGregor, G. -.I PPP Internet Protocol Control Protocol (IPCP). -May 1992. -.TP -.B RFC1334 -Lloyd, B.; Simpson, W.A. -.I PPP authentication protocols. -October 1992. -.TP -.B RFC1661 -Simpson, W.A. -.I The Point\-to\-Point Protocol (PPP). -July 1994. -.TP -.B RFC1662 -Simpson, W.A. -.I PPP in HDLC-like Framing. -July 1994. -.SH NOTES -The following signals have the specified effect when sent to pppd. -.TP -.B SIGINT, SIGTERM -These signals cause pppd to terminate the link (by closing LCP), -restore the serial device settings, and exit. -.TP -.B SIGHUP -This signal causes pppd to terminate the link, restore the serial -device settings, and close the serial device. If the \fIpersist\fR or -\fIdemand\fR option has been specified, pppd will try to reopen the -serial device and start another connection (after the holdoff period). -Otherwise pppd will exit. If this signal is received during the -holdoff period, it causes pppd to end the holdoff period immediately. -.TP -.B SIGUSR1 -This signal toggles the state of the \fIdebug\fR option. -.TP -.B SIGUSR2 -This signal causes pppd to renegotiate compression. This can be -useful to re-enable compression after it has been disabled as a result -of a fatal decompression error. (Fatal decompression errors generally -indicate a bug in one or other implementation.) - -.SH AUTHORS -Paul Mackerras (Paul.Mackerras@cs.anu.edu.au), based on earlier work by -Drew Perkins, -Brad Clements, -Karl Fox, -Greg Christy, -and -Brad Parker. diff --git a/usr.sbin/pppd/pppd.h b/usr.sbin/pppd/pppd.h deleted file mode 100644 index a547fb7..0000000 --- a/usr.sbin/pppd/pppd.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * pppd.h - PPP daemon global declarations. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * TODO: - */ - -#ifndef __PPPD_H__ -#define __PPPD_H__ - -#include <stdio.h> /* for FILE */ -#include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */ -#include <sys/types.h> /* for u_int32_t, if defined */ -#include <sys/time.h> /* for struct timeval */ -#include <net/ppp_defs.h> - -#if __STDC__ -#include <stdarg.h> -#define __V(x) x -#else -#include <varargs.h> -#define __V(x) (va_alist) va_dcl -#define const -#endif - -#ifdef INET6 -#include "eui64.h" -#endif - -/* - * Limits. - */ - -#define NUM_PPP 1 /* One PPP interface supported (per process) */ -#define MAXWORDLEN 1024 /* max length of word in file (incl null) */ -#define MAXARGS 1 /* max # args to a command */ -#define MAXNAMELEN 256 /* max length of hostname or name for auth */ -#define MAXSECRETLEN 256 /* max length of password or secret */ - -/* - * Global variables. - */ - -extern int hungup; /* Physical layer has disconnected */ -extern int ifunit; /* Interface unit number */ -extern char ifname[]; /* Interface name */ -extern int ttyfd; /* Serial device file descriptor */ -extern char hostname[]; /* Our hostname */ -extern u_char outpacket_buf[]; /* Buffer for outgoing packets */ -extern int phase; /* Current state of link - see values below */ -extern int baud_rate; /* Current link speed in bits/sec */ -extern char *progname; /* Name of this program */ -extern int redirect_stderr;/* Connector's stderr should go to file */ -extern char peer_authname[];/* Authenticated name of peer */ -extern int privileged; /* We were run by real-uid root */ -extern int need_holdoff; /* Need holdoff period after link terminates */ -extern char **script_env; /* Environment variables for scripts */ -extern int detached; /* Have detached from controlling tty */ - -/* - * Variables set by command-line options. - */ - -extern int debug; /* Debug flag */ -extern int kdebugflag; /* Tell kernel to print debug messages */ -extern int default_device; /* Using /dev/tty or equivalent */ -extern char devnam[]; /* Device name */ -extern int crtscts; /* Use hardware flow control */ -extern int modem; /* Use modem control lines */ -extern int inspeed; /* Input/Output speed requested */ -extern u_int32_t netmask; /* IP netmask to set on interface */ -extern int lockflag; /* Create lock file to lock the serial dev */ -extern int nodetach; /* Don't detach from controlling tty */ -extern char *connector; /* Script to establish physical link */ -extern char *disconnector; /* Script to disestablish physical link */ -extern char *welcomer; /* Script to welcome client after connection */ -extern int max_con_attempts;/* Maximum number of times to try dialing */ -extern int maxconnect; /* Maximum connect time (seconds) */ -extern char user[]; /* Our name for authenticating ourselves */ -extern char passwd[]; /* Password for PAP */ -extern int auth_required; /* Peer is required to authenticate */ -extern int proxyarp; /* Set up proxy ARP entry for peer */ -extern int persist; /* Reopen link after it goes down */ -extern int uselogin; /* Use /etc/passwd for checking PAP */ -extern int lcp_echo_interval; /* Interval between LCP echo-requests */ -extern int lcp_echo_fails; /* Tolerance to unanswered echo-requests */ -extern char our_name[]; /* Our name for authentication purposes */ -extern char remote_name[]; /* Peer's name for authentication */ -extern int explicit_remote;/* remote_name specified with remotename opt */ -extern int usehostname; /* Use hostname for our_name */ -extern int disable_defaultip; /* Don't use hostname for default IP adrs */ -extern int demand; /* Do dial-on-demand */ -extern char *ipparam; /* Extra parameter for ip up/down scripts */ -extern int cryptpap; /* Others' PAP passwords are encrypted */ -extern int idle_time_limit;/* Shut down link if idle for this long */ -extern int holdoff; /* Dead time before restarting */ -extern int refuse_pap; /* Don't wanna auth. ourselves with PAP */ -extern int refuse_chap; /* Don't wanna auth. ourselves with CHAP */ -#ifdef PPP_FILTER -extern struct bpf_program pass_filter; /* Filter for pkts to pass */ -extern struct bpf_program active_filter; /* Filter for link-active pkts */ -#endif - - -#ifdef MSLANMAN -extern int ms_lanman; /* Nonzero if use LanMan password instead of NT */ - /* Has meaning only with MS-CHAP challenges */ -#endif - -/* - * Values for phase. - */ -#define PHASE_DEAD 0 -#define PHASE_INITIALIZE 1 -#define PHASE_DORMANT 2 -#define PHASE_ESTABLISH 3 -#define PHASE_AUTHENTICATE 4 -#define PHASE_CALLBACK 5 -#define PHASE_NETWORK 6 -#define PHASE_TERMINATE 7 -#define PHASE_HOLDOFF 8 - -/* - * The following struct gives the addresses of procedures to call - * for a particular protocol. - */ -struct protent { - u_short protocol; /* PPP protocol number */ - /* Initialization procedure */ - void (*init)(int unit); - /* Process a received packet */ - void (*input)(int unit, u_char *pkt, int len); - /* Process a received protocol-reject */ - void (*protrej)(int unit); - /* Lower layer has come up */ - void (*lowerup)(int unit); - /* Lower layer has gone down */ - void (*lowerdown)(int unit); - /* Open the protocol */ - void (*open)(int unit); - /* Close the protocol */ - void (*close)(int unit, char *reason); - /* Print a packet in readable form */ - int (*printpkt)(u_char *pkt, int len, - void (*printer)(void *, char *, ...), - void *arg); - /* Process a received data packet */ - void (*datainput)(int unit, u_char *pkt, int len); - int enabled_flag; /* 0 iff protocol is disabled */ - char *name; /* Text name of protocol */ - /* Check requested options, assign defaults */ - void (*check_options)(void); - /* Configure interface for demand-dial */ - int (*demand_conf)(int unit); - /* Say whether to bring up link for this pkt */ - int (*active_pkt)(u_char *pkt, int len); -}; - -/* Table of pointers to supported protocols */ -extern struct protent *protocols[]; - -/* - * Prototypes. - */ - -/* Procedures exported from main.c. */ -void detach(void); /* Detach from controlling tty */ -void die(int); /* Cleanup and exit */ -void quit(void); /* like die(1) */ -void novm(char *); /* Say we ran out of memory, and die */ -void timeout(void (*func)(void *), void *arg, int t); - /* Call func(arg) after t seconds */ -void untimeout(void (*func)(void *), void *arg); - /* Cancel call to func(arg) */ -int run_program(char *prog, char **args, int must_exist); - /* Run program prog with args in child */ -void demuxprotrej(int, int); - /* Demultiplex a Protocol-Reject */ -void format_packet(u_char *, int, void (*) (void *, char *, ...), - void *); /* Format a packet in human-readable form */ -void log_packet(u_char *, int, char *, int); - /* Format a packet and log it with syslog */ -void print_string(char *, int, void (*) (void *, char *, ...), - void *); /* Format a string for output */ -int fmtmsg(char *, int, char *, ...); /* sprintf++ */ -int vfmtmsg(char *, int, char *, va_list); /* vsprintf++ */ -void script_setenv(char *, char *); /* set script env var */ -void script_unsetenv(char *); /* unset script env var */ - -/* Procedures exported from auth.c */ -void link_required(int); /* we are starting to use the link */ -void link_terminated(int); /* we are finished with the link */ -void link_down(int); /* the LCP layer has left the Opened state */ -void link_established(int); /* the link is up; authenticate now */ -void np_up(int, int); /* a network protocol has come up */ -void np_down(int, int); /* a network protocol has gone down */ -void np_finished(int, int); /* a network protocol no longer needs link */ -void auth_peer_fail(int, int); - /* peer failed to authenticate itself */ -void auth_peer_success(int, int, char *, int); - /* peer successfully authenticated itself */ -void auth_withpeer_fail(int, int); - /* we failed to authenticate ourselves */ -void auth_withpeer_success(int, int); - /* we successfully authenticated ourselves */ -void auth_check_options(void); - /* check authentication options supplied */ -void auth_reset(int); /* check what secrets we have */ -int check_passwd(int, char *, int, char *, int, char **, int *); - /* Check peer-supplied username/password */ -int get_secret(int, char *, char *, char *, int *, int); - /* get "secret" for chap */ -int auth_ip_addr(int, u_int32_t); - /* check if IP address is authorized */ -int bad_ip_adrs(u_int32_t); - /* check if IP address is unreasonable */ -void check_access(FILE *, char *); - /* check permissions on secrets file */ - -/* Procedures exported from demand.c */ -void demand_conf(void); /* config interface(s) for demand-dial */ -void demand_block(void); /* set all NPs to queue up packets */ -void demand_unblock(void); /* set all NPs to pass packets */ -void demand_discard(void); /* set all NPs to discard packets */ -void demand_rexmit(int); /* retransmit saved frames for an NP */ -int loop_chars(unsigned char *, int); /* process chars from loopback */ -int loop_frame(unsigned char *, int); /* process frame from loopback */ - -/* Procedures exported from sys-*.c */ -void sys_init(void); /* Do system-dependent initialization */ -void sys_cleanup(void); /* Restore system state before exiting */ -void sys_check_options(void); /* Check options specified */ -void sys_close(void); /* Clean up in a child before execing */ -int ppp_available(void); /* Test whether ppp kernel support exists */ -void open_ppp_loopback(void); /* Open loopback for demand-dialling */ -void establish_ppp(int); /* Turn serial port into a ppp interface */ -void restore_loop(void); /* Transfer ppp unit back to loopback */ -void disestablish_ppp(int); /* Restore port to normal operation */ -void clean_check(void); /* Check if line was 8-bit clean */ -void set_up_tty(int, int); /* Set up port's speed, parameters, etc. */ -void restore_tty(int); /* Restore port's original parameters */ -void setdtr(int, int); /* Raise or lower port's DTR line */ -void output(int, u_char *, int); /* Output a PPP packet */ -void wait_input(struct timeval *); - /* Wait for input, with timeout */ -void wait_loop_output(struct timeval *); - /* Wait for pkt from loopback, with timeout */ -void wait_time(struct timeval *); /* Wait for given length of time */ -int read_packet(u_char *); /* Read PPP packet */ -int get_loop_output(void); /* Read pkts from loopback */ -void ppp_send_config(int, int, u_int32_t, int, int); - /* Configure i/f transmit parameters */ -void ppp_set_xaccm(int, ext_accm); - /* Set extended transmit ACCM */ -void ppp_recv_config(int, int, u_int32_t, int, int); - /* Configure i/f receive parameters */ -int ccp_test(int, u_char *, int, int); - /* Test support for compression scheme */ -void ccp_flags_set(int, int, int); - /* Set kernel CCP state */ -int ccp_fatal_error(int); /* Test for fatal decomp error in kernel */ -int get_idle_time(int, struct ppp_idle *); - /* Find out how long link has been idle */ -int sifvjcomp(int, int, int, int); - /* Configure VJ TCP header compression */ -int sifup(int); /* Configure i/f up (for IP) */ -int sifnpmode(int u, int proto, enum NPmode mode); - /* Set mode for handling packets for proto */ -int sifdown(int); /* Configure i/f down (for IP) */ -int sifaddr(int, u_int32_t, u_int32_t, u_int32_t); - /* Configure IP addresses for i/f */ -int cifaddr(int, u_int32_t, u_int32_t); - /* Reset i/f IP addresses */ -#ifdef INET6 -int sif6addr(int, eui64_t, eui64_t); - /* Configure IPv6 addresses for i/f */ -int cif6addr(int, eui64_t, eui64_t); - /* Remove an IPv6 address from i/f */ -#endif -int sifdefaultroute(int, u_int32_t, u_int32_t); - /* Create default route through i/f */ -int cifdefaultroute(int, u_int32_t, u_int32_t); - /* Delete default route through i/f */ -int sifproxyarp(int, u_int32_t); - /* Add proxy ARP entry for peer */ -int cifproxyarp(int, u_int32_t); - /* Delete proxy ARP entry for peer */ -u_int32_t GetMask(u_int32_t); /* Get appropriate netmask for address */ -int lock(char *); /* Create lock file for device */ -void unlock(void); /* Delete previously-created lock file */ -int daemon(int, int); /* Detach us from terminal session */ -void logwtmp(const char *, const char *, const char *); - /* Write entry to wtmp file */ -int get_host_seed(void); /* Get host-dependent random number seed */ -#ifdef PPP_FILTER -int set_filters(struct bpf_program *pass, struct bpf_program *active); - /* Set filter programs in kernel */ -#endif - -/* Procedures exported from options.c */ -int parse_args(int argc, char **argv); - /* Parse options from arguments given */ -void usage(void); /* Print a usage message */ -int options_from_file(char *filename, int must_exist, int check_prot, - int privileged); - /* Parse options from an options file */ -int options_from_user(void); /* Parse options from user's .ppprc */ -int options_for_tty(void); /* Parse options from /etc/ppp/options.tty */ -void scan_args(int argc, char **argv); - /* Look for tty name in command-line args */ -int getword(FILE *f, char *word, int *newlinep, char *filename); - /* Read a word from a file */ -void option_error(char *fmt, ...); - /* Print an error message about an option */ -int setipaddr(char *); /* set IP addresses */ - - -/* - * This structure is used to store information about certain - * options, such as where the option value came from (/etc/ppp/options, - * command line, etc.) and whether it came from a privileged source. - */ - -struct option_info { - int priv; /* was value set by sysadmin? */ - char *source; /* where option came from */ -}; - -extern struct option_info auth_req_info; -extern struct option_info connector_info; -extern struct option_info disconnector_info; -extern struct option_info welcomer_info; -extern struct option_info devnam_info; - -/* - * Inline versions of get/put char/short/long. - * Pointer is advanced; we assume that both arguments - * are lvalues and will already be in registers. - * cp MUST be u_char *. - */ -#define GETCHAR(c, cp) { \ - (c) = *(cp)++; \ -} -#define PUTCHAR(c, cp) { \ - *(cp)++ = (u_char) (c); \ -} - - -#define GETSHORT(s, cp) { \ - (s) = *(cp)++ << 8; \ - (s) |= *(cp)++; \ -} -#define PUTSHORT(s, cp) { \ - *(cp)++ = (u_char) ((s) >> 8); \ - *(cp)++ = (u_char) (s); \ -} - -#define GETLONG(l, cp) { \ - (l) = *(cp)++ << 8; \ - (l) |= *(cp)++; (l) <<= 8; \ - (l) |= *(cp)++; (l) <<= 8; \ - (l) |= *(cp)++; \ -} -#define PUTLONG(l, cp) { \ - *(cp)++ = (u_char) ((l) >> 24); \ - *(cp)++ = (u_char) ((l) >> 16); \ - *(cp)++ = (u_char) ((l) >> 8); \ - *(cp)++ = (u_char) (l); \ -} - -#define INCPTR(n, cp) ((cp) += (n)) -#define DECPTR(n, cp) ((cp) -= (n)) - -#undef FALSE -#define FALSE 0 -#undef TRUE -#define TRUE 1 - -/* - * System dependent definitions for user-level 4.3BSD UNIX implementation. - */ - -#define DEMUXPROTREJ(u, p) demuxprotrej(u, p) - -#define TIMEOUT(r, f, t) timeout((r), (f), (t)) -#define UNTIMEOUT(r, f) untimeout((r), (f)) - -#define BCOPY(s, d, l) memcpy(d, s, l) -#define BZERO(s, n) memset(s, 0, n) -#define EXIT(u) quit() - -#define PRINTMSG(m, l) { m[l] = '\0'; syslog(LOG_INFO, "Remote message: %s", m); } - -/* - * MAKEHEADER - Add Header fields to a packet. - */ -#define MAKEHEADER(p, t) { \ - PUTCHAR(PPP_ALLSTATIONS, p); \ - PUTCHAR(PPP_UI, p); \ - PUTSHORT(t, p); } - - -#ifdef DEBUGALL -#define DEBUGMAIN 1 -#define DEBUGFSM 1 -#define DEBUGLCP 1 -#define DEBUGIPCP 1 -#define DEBUGUPAP 1 -#define DEBUGCHAP 1 -#endif - -#ifndef LOG_PPP /* we use LOG_LOCAL2 for syslog by default */ -#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \ - || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \ - || defined(DEBUGCHAP) || defined(DEBUG) -#define LOG_PPP LOG_LOCAL2 -#else -#define LOG_PPP LOG_DAEMON -#endif -#endif /* LOG_PPP */ - -#ifdef DEBUGMAIN -#define MAINDEBUG(x) if (debug) syslog x -#else -#define MAINDEBUG(x) -#endif - -#ifdef DEBUGSYS -#define SYSDEBUG(x) if (debug) syslog x -#else -#define SYSDEBUG(x) -#endif - -#ifdef DEBUGFSM -#define FSMDEBUG(x) if (debug) syslog x -#else -#define FSMDEBUG(x) -#endif - -#ifdef DEBUGLCP -#define LCPDEBUG(x) if (debug) syslog x -#else -#define LCPDEBUG(x) -#endif - -#ifdef DEBUGIPCP -#define IPCPDEBUG(x) if (debug) syslog x -#else -#define IPCPDEBUG(x) -#endif - -#ifdef DEBUGIPV6CP -#define IPV6CPDEBUG(x) if (debug) syslog x -#else -#define IPV6CPDEBUG(x) -#endif - -#ifdef DEBUGUPAP -#define UPAPDEBUG(x) if (debug) syslog x -#else -#define UPAPDEBUG(x) -#endif - -#ifdef DEBUGCHAP -#define CHAPDEBUG(x) if (debug) syslog x -#else -#define CHAPDEBUG(x) -#endif - -#ifdef DEBUGIPXCP -#define IPXCPDEBUG(x) if (debug) syslog x -#else -#define IPXCPDEBUG(x) -#endif - -#ifndef SIGTYPE -#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) -#define SIGTYPE void -#else -#define SIGTYPE int -#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */ -#endif /* SIGTYPE */ - -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a): (b)) -#endif -#ifndef MAX -#define MAX(a, b) ((a) > (b)? (a): (b)) -#endif - -#endif /* __PPP_H__ */ diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c deleted file mode 100644 index cbde7a4..0000000 --- a/usr.sbin/pppd/sys-bsd.c +++ /dev/null @@ -1,1697 +0,0 @@ -/* - * 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. - * Copyright (c) 1995 The Australian National 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 and The Australian National University. - * The names of the Universities 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif -/* $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */ - -/* - * TODO: - */ - -#include <stdio.h> -#include <syslog.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <termios.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <sys/module.h> -#ifdef NetBSD1_2 -#include <util.h> -#endif -#ifdef PPP_FILTER -#include <net/bpf.h> -#endif - -#include <net/if.h> -#include <net/ppp_defs.h> -#include <net/if_ppp.h> -#include <net/route.h> -#include <net/if_dl.h> -#include <netinet/in.h> -#include <net/if_var.h> -#include <netinet6/in6_var.h> -#include <netinet6/nd6.h> -#include <ifaddrs.h> - -#ifdef IPX_CHANGE -#include <netipx/ipx.h> -#endif - -#if RTM_VERSION >= 3 -#include <sys/param.h> -#if defined(NetBSD) && (NetBSD >= 199703) -#include <netinet/if_inarp.h> -#else /* NetBSD 1.2D or later */ -#ifdef __FreeBSD__ -#include <netinet/if_ether.h> -#else -#include <net/if_ether.h> -#endif -#endif -#endif - -#include <ifaddrs.h> - -#include "pppd.h" -#include "fsm.h" -#include "ipcp.h" - -static int initdisc = -1; /* Initial TTY discipline for ppp_fd */ -static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */ -static int ppp_fd = -1; /* fd which is set to PPP discipline */ -static int rtm_seq; - -static int restore_term; /* 1 => we've munged the terminal */ -static struct termios inittermios; /* Initial TTY termios */ -static struct winsize wsinfo; /* Initial window size info */ - -static char *lock_file; /* name of lock file created */ - -static int loop_slave = -1; -static int loop_master; -static char loop_name[20]; - -static unsigned char inbuf[512]; /* buffer for chars read from loopback */ - -static int sockfd; /* socket for doing interface ioctls */ -#ifdef INET6 -static int sock6_fd = -1; /* socket for doing ipv6 interface ioctls */ -#endif /* INET6 */ - -static int if_is_up; /* the interface is currently up */ -static u_int32_t ifaddrs[2]; /* local and remote addresses we set */ -static u_int32_t default_route_gateway; /* gateway addr for default route */ -static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */ - -/* Prototypes for procedures local to this file. */ -static int dodefaultroute(u_int32_t, int); -static int get_ether_addr(u_int32_t, struct sockaddr_dl *); - - -/* - * sys_init - System-dependent initialization. - */ -void -sys_init() -{ - /* Get an internet socket for doing socket ioctl's on. */ - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "Couldn't create IP socket: %m"); - die(1); - } - -#ifdef INET6 - if ((sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - /* check it at runtime */ - sock6_fd = -1; - } -#endif -} - -/* - * sys_cleanup - restore any system state we modified before exiting: - * mark the interface down, delete default route and/or proxy arp entry. - * This should call die() because it's called from die(). - */ -void -sys_cleanup() -{ - struct ifreq ifr; - - if (if_is_up) { - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0 - && ((ifr.ifr_flags & IFF_UP) != 0)) { - ifr.ifr_flags &= ~IFF_UP; - ioctl(sockfd, SIOCSIFFLAGS, &ifr); - } - } - if (ifaddrs[0] != 0) - cifaddr(0, ifaddrs[0], ifaddrs[1]); - if (default_route_gateway) - cifdefaultroute(0, 0, default_route_gateway); - if (proxy_arp_addr) - cifproxyarp(0, proxy_arp_addr); -} - -/* - * sys_close - Clean up in a child process before execing. - */ -void -sys_close() -{ - if (sockfd >= 0) - close(sockfd); -#ifdef INET6 - if (sock6_fd >= 0) - close(sock6_fd); -#endif - if (loop_slave >= 0) { - close(loop_slave); - close(loop_master); - } -} - -/* - * sys_check_options - check the options that the user specified - */ -void -sys_check_options() -{ -} - -/* - * ppp_available - check whether the system has the ppp module loaded - * or compiled in. If it doesn't, and we're actually root (not just SUID - * root) try loading it before giving up. - */ -int -ppp_available() -{ - const char *modname = "if_ppp"; - extern char *no_ppp_msg; - - if (modfind(modname) != -1) { - return 1; - } - - if (getuid() == 0 && kldload(modname) != -1) - return 1; - - no_ppp_msg = "\ -This system lacks kernel support for PPP. To include PPP support\n\ -in the kernel, please add \"device ppp\" to your kernel config or \n\ -load the if_ppp module.\n"; - - return 0; -} - -/* - * establish_ppp - Turn the serial port into a ppp interface. - */ -void -establish_ppp(fd) - int fd; -{ - int pppdisc = PPPDISC; - int x; - - if (demand) { - /* - * Demand mode - prime the old ppp device to relinquish the unit. - */ - if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) { - syslog(LOG_ERR, "ioctl(transfer ppp unit): %m"); - die(1); - } - } - - /* - * Save the old line discipline of fd, and set it to PPP. - */ - if (ioctl(fd, TIOCGETD, &initdisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCGETD): %m"); - die(1); - } - if (ioctl(fd, TIOCSETD, &pppdisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - die(1); - } - - if (!demand) { - /* - * Find out which interface we were given. - */ - if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); - die(1); - } - } else { - /* - * Check that we got the same unit again. - */ - if (ioctl(fd, PPPIOCGUNIT, &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); - die(1); - } - if (x != ifunit) { - syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d", - ifunit, x); - die(1); - } - x = TTYDISC; - ioctl(loop_slave, TIOCSETD, &x); - } - - ppp_fd = fd; - - /* - * Enable debug in the driver if requested. - */ - if (kdebugflag) { - if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m"); - } else { - x |= (kdebugflag & 0xFF) * SC_DEBUG; - if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) - syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m"); - } - } - - /* - * Set device for non-blocking reads. - */ - if ((initfdflags = fcntl(fd, F_GETFL)) == -1 - || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) { - syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m"); - } -} - -/* - * restore_loop - reattach the ppp unit to the loopback. - */ -void -restore_loop() -{ - int x; - - /* - * Transfer the ppp interface back to the loopback. - */ - if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) { - syslog(LOG_ERR, "ioctl(transfer ppp unit): %m"); - die(1); - } - x = PPPDISC; - if (ioctl(loop_slave, TIOCSETD, &x) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - die(1); - } - - /* - * Check that we got the same unit again. - */ - if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); - die(1); - } - if (x != ifunit) { - syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d", - ifunit, x); - die(1); - } - ppp_fd = loop_slave; -} - - -/* - * disestablish_ppp - Restore the serial port to normal operation. - * This shouldn't call die() because it's called from die(). - */ -void -disestablish_ppp(fd) - int fd; -{ - /* Reset non-blocking mode on fd. */ - if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0) - syslog(LOG_WARNING, "Couldn't restore device fd flags: %m"); - initfdflags = -1; - - /* Restore old line discipline. */ - if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0) - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - initdisc = -1; - - if (fd == ppp_fd) - ppp_fd = -1; -} - -/* - * Check whether the link seems not to be 8-bit clean. - */ -void -clean_check() -{ - int x; - char *s; - - if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { - s = NULL; - switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { - case SC_RCV_B7_0: - s = "bit 7 set to 1"; - break; - case SC_RCV_B7_1: - s = "bit 7 set to 0"; - break; - case SC_RCV_EVNP: - s = "odd parity"; - break; - case SC_RCV_ODDP: - s = "even parity"; - break; - } - if (s != NULL) { - syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); - syslog(LOG_WARNING, "All received characters had %s", s); - } - } -} - -/* - * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, - * at the requested speed, etc. If `local' is true, set CLOCAL - * regardless of whether the modem option was specified. - * - * For *BSD, we assume that speed_t values numerically equal bits/second. - */ -void -set_up_tty(fd, local) - int fd, local; -{ - struct termios tios; - - if (tcgetattr(fd, &tios) < 0) { - syslog(LOG_ERR, "tcgetattr: %m"); - die(1); - } - - if (!restore_term) { - inittermios = tios; - ioctl(fd, TIOCGWINSZ, &wsinfo); - } - - tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); - if (crtscts > 0 && !local) - tios.c_cflag |= CRTSCTS; - else if (crtscts < 0) - tios.c_cflag &= ~CRTSCTS; - - tios.c_cflag |= CS8 | CREAD | HUPCL; - if (local || !modem) - tios.c_cflag |= CLOCAL; - tios.c_iflag = IGNBRK | IGNPAR; - tios.c_oflag = 0; - tios.c_lflag = 0; - tios.c_cc[VMIN] = 1; - tios.c_cc[VTIME] = 0; - - if (crtscts == -2) { - tios.c_iflag |= IXON | IXOFF; - tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ - tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ - } - - if (inspeed) { - cfsetospeed(&tios, inspeed); - cfsetispeed(&tios, inspeed); - } else { - inspeed = cfgetospeed(&tios); - /* - * We can't proceed if the serial port speed is 0, - * since that implies that the serial port is disabled. - */ - if (inspeed == 0) { - syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate", - devnam); - die(1); - } - } - baud_rate = inspeed; - - if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { - syslog(LOG_ERR, "tcsetattr: %m"); - die(1); - } - - restore_term = 1; -} - -/* - * restore_tty - restore the terminal to the saved settings. - */ -void -restore_tty(fd) - int fd; -{ - if (restore_term) { - if (!default_device) { - /* - * Turn off echoing, because otherwise we can get into - * a loop with the tty and the modem echoing to each other. - * We presume we are the sole user of this tty device, so - * when we close it, it will revert to its defaults anyway. - */ - inittermios.c_lflag &= ~(ECHO | ECHONL); - } - if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) - if (errno != ENXIO) - syslog(LOG_WARNING, "tcsetattr: %m"); - ioctl(fd, TIOCSWINSZ, &wsinfo); - restore_term = 0; - } -} - -/* - * setdtr - control the DTR line on the serial port. - * This is called from die(), so it shouldn't call die(). - */ -void -setdtr(fd, on) -int fd, on; -{ - int modembits = TIOCM_DTR; - - ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); -} - -#ifdef INET6 -/* - * sif6addr - Config the interface with an IPv6 link-local address - */ -int -sif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64) -{ - int ifindex; - struct in6_aliasreq addreq6; - - if (sock6_fd < 0) { - syslog(LOG_ERR, "No IPv6 socket available"); - die(1); - /*NOTREACHED*/ - } - - /* actually, this part is not kame local - RFC2553 conformant */ - ifindex = if_nametoindex(ifname); - if (ifindex == 0) { - syslog(LOG_ERR, "sifaddr6: no interface %s", ifname); - return 0; - } - - memset(&addreq6, 0, sizeof(addreq6)); - strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name)); - - /* my addr */ - addreq6.ifra_addr.sin6_family = AF_INET6; - addreq6.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); - addreq6.ifra_addr.sin6_addr.s6_addr[0] = 0xfe; - addreq6.ifra_addr.sin6_addr.s6_addr[1] = 0x80; - memcpy(&addreq6.ifra_addr.sin6_addr.s6_addr[8], &our_eui64, - sizeof(our_eui64)); - /* KAME ifindex hack */ - *(u_int16_t *)&addreq6.ifra_addr.sin6_addr.s6_addr[2] = htons(ifindex); - - /* his addr */ - addreq6.ifra_dstaddr.sin6_family = AF_INET6; - addreq6.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6); - addreq6.ifra_dstaddr.sin6_addr.s6_addr[0] = 0xfe; - addreq6.ifra_dstaddr.sin6_addr.s6_addr[1] = 0x80; - memcpy(&addreq6.ifra_dstaddr.sin6_addr.s6_addr[8], &his_eui64, - sizeof(our_eui64)); - /* KAME ifindex hack */ - *(u_int16_t *)&addreq6.ifra_dstaddr.sin6_addr.s6_addr[2] = htons(ifindex); - - /* prefix mask: 128bit */ - addreq6.ifra_prefixmask.sin6_family = AF_INET6; - addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6); - memset(&addreq6.ifra_prefixmask.sin6_addr, 0xff, - sizeof(addreq6.ifra_prefixmask.sin6_addr)); - - /* address lifetime (infty) */ - addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; - addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; - - if (ioctl(sock6_fd, SIOCAIFADDR_IN6, &addreq6) < 0) { - syslog(LOG_ERR, "sif6addr: ioctl(SIOCAIFADDR_IN6): %m"); - return 0; - } - - return 1; -} - - -/* - * cif6addr - Remove IPv6 address from interface - */ -int -cif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64) -{ - int ifindex; - struct in6_ifreq delreq6; - - if (sock6_fd < 0) { - syslog(LOG_ERR, "No IPv6 socket available"); - die(1); - /*NOTREACHED*/ - } - - /* actually, this part is not kame local - RFC2553 conformant */ - ifindex = if_nametoindex(ifname); - if (ifindex == 0) { - syslog(LOG_ERR, "cifaddr6: no interface %s", ifname); - return 0; - } - - memset(&delreq6, 0, sizeof(delreq6)); - strlcpy(delreq6.ifr_name, ifname, sizeof(delreq6.ifr_name)); - - /* my addr */ - delreq6.ifr_ifru.ifru_addr.sin6_family = AF_INET6; - delreq6.ifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6); - delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[0] = 0xfe; - delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[1] = 0x80; - memcpy(&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[8], &our_eui64, - sizeof(our_eui64)); - /* KAME ifindex hack */ - *(u_int16_t *)&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[2] = - htons(ifindex); - - if (ioctl(sock6_fd, SIOCDIFADDR_IN6, &delreq6) < 0) { - syslog(LOG_ERR, "cif6addr: ioctl(SIOCDIFADDR_IN6): %m"); - return 0; - } - - return 1; -} -#endif /* INET6 */ - -/* - * open_ppp_loopback - open the device we use for getting - * packets in demand mode, and connect it to a ppp interface. - * Here we use a pty. - */ -void -open_ppp_loopback() -{ - int flags; - struct termios tios; - int pppdisc = PPPDISC; - - if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) { - syslog(LOG_ERR, "No free pty for loopback"); - die(1); - } - SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name)); - - if (tcgetattr(loop_slave, &tios) == 0) { - tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB); - tios.c_cflag |= CS8 | CREAD; - tios.c_iflag = IGNPAR; - tios.c_oflag = 0; - tios.c_lflag = 0; - if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0) - syslog(LOG_WARNING, "couldn't set attributes on loopback: %m"); - } - - if ((flags = fcntl(loop_master, F_GETFL)) != -1) - if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1) - syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m"); - - ppp_fd = loop_slave; - if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - die(1); - } - - /* - * Find out which interface we were given. - */ - if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); - die(1); - } - - /* - * Enable debug in the driver if requested. - */ - if (kdebugflag) { - if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) { - syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m"); - } else { - flags |= (kdebugflag & 0xFF) * SC_DEBUG; - if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0) - syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m"); - } - } - -} - - -/* - * output - Output PPP packet. - */ -void -output(unit, p, len) - int unit; - u_char *p; - int len; -{ - if (debug) - log_packet(p, len, "sent ", LOG_DEBUG); - - if (write(ttyfd, p, len) < 0) { - if (errno != EIO) - syslog(LOG_ERR, "write: %m"); - } -} - - -/* - * wait_input - wait until there is data available on ttyfd, - * for the length of time specified by *timo (indefinite - * if timo is NULL). - */ -void -wait_input(timo) - struct timeval *timo; -{ - fd_set ready; - int n; - - if (ttyfd >= FD_SETSIZE) { - syslog(LOG_ERR, "descriptor too big"); - die(1); - } - FD_ZERO(&ready); - FD_SET(ttyfd, &ready); - n = select(ttyfd+1, &ready, NULL, &ready, timo); - if (n < 0 && errno != EINTR) { - syslog(LOG_ERR, "select: %m"); - die(1); - } -} - - -/* - * wait_loop_output - wait until there is data available on the - * loopback, for the length of time specified by *timo (indefinite - * if timo is NULL). - */ -void -wait_loop_output(timo) - struct timeval *timo; -{ - fd_set ready; - int n; - - if (loop_master >= FD_SETSIZE) { - syslog(LOG_ERR, "descriptor too big"); - die(1); - } - FD_ZERO(&ready); - FD_SET(loop_master, &ready); - n = select(loop_master + 1, &ready, NULL, &ready, timo); - if (n < 0 && errno != EINTR) { - syslog(LOG_ERR, "select: %m"); - die(1); - } -} - - -/* - * wait_time - wait for a given length of time or until a - * signal is received. - */ -void -wait_time(timo) - struct timeval *timo; -{ - int n; - - n = select(0, NULL, NULL, NULL, timo); - if (n < 0 && errno != EINTR) { - syslog(LOG_ERR, "select: %m"); - die(1); - } -} - - -/* - * read_packet - get a PPP packet from the serial device. - */ -int -read_packet(buf) - u_char *buf; -{ - int len; - - if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return -1; - syslog(LOG_ERR, "read: %m"); - die(1); - } - return len; -} - - -/* - * get_loop_output - read characters from the loopback, form them - * into frames, and detect when we want to bring the real link up. - * Return value is 1 if we need to bring up the link, 0 otherwise. - */ -int -get_loop_output() -{ - int rv = 0; - int n; - - while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) { - if (loop_chars(inbuf, n)) - rv = 1; - } - - if (n == 0) { - syslog(LOG_ERR, "eof on loopback"); - die(1); - } else if (errno != EWOULDBLOCK){ - syslog(LOG_ERR, "read from loopback: %m"); - die(1); - } - - return rv; -} - - -/* - * ppp_send_config - configure the transmit characteristics of - * the ppp interface. - */ -void -ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) - int unit, mtu; - u_int32_t asyncmap; - int pcomp, accomp; -{ - u_int x; - struct ifreq ifr; - - strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - ifr.ifr_mtu = mtu; - if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m"); - quit(); - } - - if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m"); - quit(); - } - - if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - quit(); - } - x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT; - x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC; - if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - quit(); - } -} - - -/* - * ppp_set_xaccm - set the extended transmit ACCM for the interface. - */ -void -ppp_set_xaccm(unit, accm) - int unit; - ext_accm accm; -{ - if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) - syslog(LOG_WARNING, "ioctl(set extended ACCM): %m"); -} - - -/* - * ppp_recv_config - configure the receive-side characteristics of - * the ppp interface. - */ -void -ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) - int unit, mru; - u_int32_t asyncmap; - int pcomp, accomp; -{ - int x; - - if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m"); - quit(); - } - if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m"); - quit(); - } - if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - quit(); - } - x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC; - if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - quit(); - } -} - -/* - * ccp_test - ask kernel whether a given compression method - * is acceptable for use. Returns 1 if the method and parameters - * are OK, 0 if the method is known but the parameters are not OK - * (e.g. code size should be reduced), or -1 if the method is unknown. - */ -int -ccp_test(unit, opt_ptr, opt_len, for_transmit) - int unit, opt_len, for_transmit; - u_char *opt_ptr; -{ - struct ppp_option_data data; - - data.ptr = opt_ptr; - data.length = opt_len; - data.transmit = for_transmit; - if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0) - return 1; - return (errno == ENOBUFS)? 0: -1; -} - -/* - * ccp_flags_set - inform kernel about the current state of CCP. - */ -void -ccp_flags_set(unit, isopen, isup) - int unit, isopen, isup; -{ - int x; - - if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - return; - } - x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN; - x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP; - if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) - syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); -} - -/* - * ccp_fatal_error - returns 1 if decompression was disabled as a - * result of an error detected after decompression of a packet, - * 0 otherwise. This is necessary because of patent nonsense. - */ -int -ccp_fatal_error(unit) - int unit; -{ - int x; - - if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m"); - return 0; - } - return x & SC_DC_FERROR; -} - -/* - * get_idle_time - return how long the link has been idle. - */ -int -get_idle_time(u, ip) - int u; - struct ppp_idle *ip; -{ - return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0; -} - - -#ifdef PPP_FILTER -/* - * set_filters - transfer the pass and active filters to the kernel. - */ -int -set_filters(pass, active) - struct bpf_program *pass, *active; -{ - int ret = 1; - - if (pass->bf_len > 0) { - if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) { - syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m"); - ret = 0; - } - } - if (active->bf_len > 0) { - if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) { - syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m"); - ret = 0; - } - } - return ret; -} -#endif - -/* - * sifvjcomp - config tcp header compression - */ -int -sifvjcomp(u, vjcomp, cidcomp, maxcid) - int u, vjcomp, cidcomp, maxcid; -{ - u_int x; - - if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - return 0; - } - x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP; - x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID; - if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - return 0; - } - if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - return 0; - } - return 1; -} - -/* - * sifup - Config the interface up and enable IP packets to pass. - */ -int -sifup(u) - int u; -{ - struct ifreq ifr; - - strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); - return 0; - } - ifr.ifr_flags |= IFF_UP; - if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); - return 0; - } - if_is_up = 1; - return 1; -} - -/* - * sifnpmode - Set the mode for handling packets for a given NP. - */ -int -sifnpmode(u, proto, mode) - int u; - int proto; - enum NPmode mode; -{ - struct npioctl npi; - - npi.protocol = proto; - npi.mode = mode; - if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) { - syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode); - return 0; - } - return 1; -} - -/* - * sifdown - Config the interface down and disable IP. - */ -int -sifdown(u) - int u; -{ - struct ifreq ifr; - int rv; - struct npioctl npi; - - rv = 1; - npi.protocol = PPP_IP; - npi.mode = NPMODE_ERROR; - ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi); - /* ignore errors, because ppp_fd might have been closed by now. */ - - strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); - rv = 0; - } else { - ifr.ifr_flags &= ~IFF_UP; - if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); - rv = 0; - } else - if_is_up = 0; - } - return rv; -} - -/* - * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, - * if it exists. - */ -#define SET_SA_FAMILY(addr, family) \ - BZERO((char *) &(addr), sizeof(addr)); \ - addr.sa_family = (family); \ - addr.sa_len = sizeof(addr); - -/* - * sifaddr - Config the interface IP addresses and netmask. - */ -int -sifaddr(u, o, h, m) - int u; - u_int32_t o, h, m; -{ - struct ifaliasreq ifra; - struct ifreq ifr; - - strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); - SET_SA_FAMILY(ifra.ifra_addr, AF_INET); - ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; - SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); - ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; - if (m != 0) { - SET_SA_FAMILY(ifra.ifra_mask, AF_INET); - ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m; - } else - BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); - BZERO(&ifr, sizeof(ifr)); - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { - if (errno != EADDRNOTAVAIL) - syslog(LOG_WARNING, "Couldn't remove interface address: %m"); - } - if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { - if (errno != EEXIST) { - syslog(LOG_ERR, "Couldn't set interface address: %m"); - return 0; - } - syslog(LOG_WARNING, - "Couldn't set interface address: Address %s already exists", - ip_ntoa(o)); - } - ifaddrs[0] = o; - ifaddrs[1] = h; - return 1; -} - -/* - * cifaddr - Clear the interface IP addresses, and delete routes - * through the interface if possible. - */ -int -cifaddr(u, o, h) - int u; - u_int32_t o, h; -{ - struct ifaliasreq ifra; - - ifaddrs[0] = 0; - strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); - SET_SA_FAMILY(ifra.ifra_addr, AF_INET); - ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; - SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); - ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; - BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); - if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) { - if (errno != EADDRNOTAVAIL) - syslog(LOG_WARNING, "Couldn't delete interface address: %m"); - return 0; - } - return 1; -} - -/* - * sifdefaultroute - assign a default route through the address given. - */ -int -sifdefaultroute(u, l, g) - int u; - u_int32_t l, g; -{ - return dodefaultroute(g, 's'); -} - -/* - * cifdefaultroute - delete a default route through the address given. - */ -int -cifdefaultroute(u, l, g) - int u; - u_int32_t l, g; -{ - return dodefaultroute(g, 'c'); -} - -/* - * dodefaultroute - talk to a routing socket to add/delete a default route. - */ -static int -dodefaultroute(g, cmd) - u_int32_t g; - int cmd; -{ - int routes; - struct { - struct rt_msghdr hdr; - struct sockaddr_in dst; - struct sockaddr_in gway; - struct sockaddr_in mask; - } rtmsg; - - if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { - syslog(LOG_ERR, "Couldn't %s default route: socket: %m", - cmd=='s'? "add": "delete"); - return 0; - } - - memset(&rtmsg, 0, sizeof(rtmsg)); - rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE; - rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; - rtmsg.hdr.rtm_version = RTM_VERSION; - rtmsg.hdr.rtm_seq = ++rtm_seq; - rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; - rtmsg.dst.sin_len = sizeof(rtmsg.dst); - rtmsg.dst.sin_family = AF_INET; - rtmsg.gway.sin_len = sizeof(rtmsg.gway); - rtmsg.gway.sin_family = AF_INET; - rtmsg.gway.sin_addr.s_addr = g; - rtmsg.mask.sin_len = sizeof(rtmsg.dst); - rtmsg.mask.sin_family = AF_INET; - - rtmsg.hdr.rtm_msglen = sizeof(rtmsg); - if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) { - syslog(LOG_ERR, "Couldn't %s default route: %m", - cmd=='s'? "add": "delete"); - close(routes); - return 0; - } - - close(routes); - default_route_gateway = (cmd == 's')? g: 0; - return 1; -} - -#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(unit, hisaddr) - int unit; - u_int32_t 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(hisaddr, &arpmsg.hwa)) { - syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP"); - return 0; - } - - if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { - syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m"); - 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; - 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) { - syslog(LOG_ERR, "Couldn't add proxy arp entry: %m"); - close(routes); - return 0; - } - - close(routes); - arpmsg_valid = 1; - proxy_arp_addr = hisaddr; - return 1; -} - -/* - * cifproxyarp - Delete the proxy ARP entry for the peer. - */ -int -cifproxyarp(unit, hisaddr) - int unit; - u_int32_t hisaddr; -{ - int routes; - - if (!arpmsg_valid) - return 0; - arpmsg_valid = 0; - - arpmsg.hdr.rtm_type = RTM_DELETE; - arpmsg.hdr.rtm_seq = ++rtm_seq; - - if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { - syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m"); - return 0; - } - - if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { - syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m"); - close(routes); - return 0; - } - - close(routes); - proxy_arp_addr = 0; - return 1; -} - -#else /* RTM_VERSION */ - -/* - * sifproxyarp - Make a proxy ARP entry for the peer. - */ -int -sifproxyarp(unit, hisaddr) - int unit; - u_int32_t hisaddr; -{ - struct arpreq arpreq; - struct { - struct sockaddr_dl sdl; - char space[128]; - } dls; - - BZERO(&arpreq, sizeof(arpreq)); - - /* - * Get the hardware address of an interface on the same subnet - * as our local address. - */ - if (!get_ether_addr(hisaddr, &dls.sdl)) { - syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP"); - return 0; - } - - arpreq.arp_ha.sa_len = sizeof(struct sockaddr); - arpreq.arp_ha.sa_family = AF_UNSPEC; - BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen); - SET_SA_FAMILY(arpreq.arp_pa, AF_INET); - ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; - arpreq.arp_flags = ATF_PERM | ATF_PUBL; - if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) { - syslog(LOG_ERR, "Couldn't add proxy arp entry: %m"); - return 0; - } - - proxy_arp_addr = hisaddr; - return 1; -} - -/* - * cifproxyarp - Delete the proxy ARP entry for the peer. - */ -int -cifproxyarp(unit, hisaddr) - int unit; - u_int32_t hisaddr; -{ - struct arpreq arpreq; - - BZERO(&arpreq, sizeof(arpreq)); - SET_SA_FAMILY(arpreq.arp_pa, AF_INET); - ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; - if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) { - syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m"); - return 0; - } - proxy_arp_addr = 0; - return 1; -} -#endif /* RTM_VERSION */ - -#ifdef IPX_CHANGE -/******************************************************************** - * - * sipxfaddr - Config the interface IPX networknumber - */ - -int -sipxfaddr (int unit, unsigned long int network, unsigned char * node ) - { - int result = 1; - - int skfd; - struct sockaddr_ipx ipx_addr; - struct ifreq ifr; - struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; - union ipx_net_u net; - - skfd = socket (AF_IPX, SOCK_DGRAM, 0); - if (skfd < 0) - { - syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno); - result = 0; - } - else - { - memset (&ifr, '\0', sizeof (ifr)); - strcpy (ifr.ifr_name, ifname); - - memcpy (sipx->sipx_addr.x_host.c_host, node, 6); - sipx->sipx_len = sizeof(sipx); - sipx->sipx_family = AF_IPX; - sipx->sipx_port = 0; - memset(&net, 0, sizeof(net)); - net.long_e = htonl (network); - sipx->sipx_addr.x_net = net.net_e; -/* - * Set the IPX device - */ - if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) - { - result = 0; - if (errno != EEXIST) - { - syslog (LOG_DEBUG, - "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno); - } - else - { - syslog (LOG_WARNING, - "ioctl(SIOCAIFADDR, CRTITF): Address already exists"); - } - } - close (skfd); - } - return result; - } - -/******************************************************************** - * - * cipxfaddr - Clear the information for the IPX network. The IPX routes - * are removed and the device is no longer able to pass IPX - * frames. - */ - -int cipxfaddr (int unit) - { - int result = 1; - - int skfd; - struct sockaddr_ipx ipx_addr; - struct ifreq ifr; - struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr; - - skfd = socket (AF_IPX, SOCK_DGRAM, 0); - if (skfd < 0) - { - syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno); - result = 0; - } - else - { - memset (&ifr, '\0', sizeof (ifr)); - strcpy (ifr.ifr_name, ifname); - - sipx->sipx_len = sizeof(sipx); - sipx->sipx_family = AF_IPX; -/* - * Set the IPX device - */ - if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) - { - syslog (LOG_INFO, - "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno); - result = 0; - } - close (skfd); - } - return result; - } -#endif - -/* - * get_ether_addr - get the hardware address of an interface on the - * the same subnet as ipaddr. - */ -static int -get_ether_addr(ipaddr, hwaddr) - u_int32_t ipaddr; - struct sockaddr_dl *hwaddr; -{ - u_int32_t ina, mask; - struct sockaddr_dl *dla; - struct ifaddrs *ifap, *ifa, *ifp; - - /* - * Scan through looking for an interface with an Internet - * address on the same subnet as `ipaddr'. - */ - if (getifaddrs(&ifap) != 0) { - syslog(LOG_ERR, "getifaddrs: %m"); - return 0; - } - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - ina = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr; - /* - * Check that the interface is up, and not point-to-point - * or loopback. - */ - if ((ifa->ifa_flags & - (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) - != (IFF_UP|IFF_BROADCAST)) - continue; - /* - * Get its netmask and check that it's on the right subnet. - */ - mask = ((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr; - if ((ipaddr & mask) != (ina & mask)) - continue; - break; - } - if (!ifa) { - freeifaddrs(ifap); - return 0; - } - syslog(LOG_INFO, "found interface %s for proxy arp", ifa->ifa_name); - - /* - * Now scan through again looking for a link-level address - * for this interface. - */ - ifp = ifa; - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (strcmp(ifp->ifa_name, ifa->ifa_name) != 0) - continue; - if (ifa->ifa_addr->sa_family != AF_LINK) - continue; - /* - * Found the link-level address - copy it out - */ - dla = (struct sockaddr_dl *) ifa->ifa_addr; - BCOPY(dla, hwaddr, dla->sdl_len); - freeifaddrs(ifap); - return 1; - } - - freeifaddrs(ifap); - return 0; -} - -/* - * Return user specified netmask, modified by any mask we might determine - * for address `addr' (in network byte order). - * Here we scan through the system's list of interfaces, looking for - * any non-point-to-point interfaces which might appear to be on the same - * network as `addr'. If we find any, we OR in their netmask to the - * user-specified netmask. - */ -u_int32_t -GetMask(addr) - u_int32_t addr; -{ - u_int32_t mask, nmask, ina; - struct ifaddrs *ifap, *ifa; - - addr = ntohl(addr); - if (IN_CLASSA(addr)) /* determine network mask for address class */ - nmask = IN_CLASSA_NET; - else if (IN_CLASSB(addr)) - nmask = IN_CLASSB_NET; - else - nmask = IN_CLASSC_NET; - /* class D nets are disallowed by bad_ip_adrs */ - mask = netmask | htonl(nmask); - - /* - * Scan through the system's network interfaces. - */ - if (getifaddrs(&ifap) != 0) { - syslog(LOG_WARNING, "getifaddrs: %m"); - return mask; - } - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - /* - * Check the interface's internet address. - */ - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - ina = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr; - if ((ntohl(ina) & nmask) != (addr & nmask)) - continue; - /* - * Check that the interface is up, and not point-to-point or loopback. - */ - if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP) - continue; - /* - * Get its netmask and OR it into our mask. - */ - mask |= ((struct sockaddr_in *)&ifa->ifa_netmask)->sin_addr.s_addr; - } - - freeifaddrs(ifap); - return mask; -} - -/* - * Use the hostid as part of the random number seed. - */ -int -get_host_seed() -{ - return gethostid(); -} - -/* - * lock - create a lock file for the named lock device - */ -#define LOCK_PREFIX "/var/spool/lock/LCK.." - -int -lock(dev) - char *dev; -{ - char hdb_lock_buffer[12]; - int fd, pid, n; - char *p; - - if ((p = strrchr(dev, '/')) != NULL) - dev = p + 1; - lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1); - if (lock_file == NULL) - novm("lock file name"); - strcat(strcpy(lock_file, LOCK_PREFIX), dev); - - while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { - if (errno == EEXIST - && (fd = open(lock_file, O_RDONLY, 0)) >= 0) { - /* Read the lock file to find out who has the device locked */ - n = read(fd, hdb_lock_buffer, 11); - if (n <= 0) { - syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file); - close(fd); - } else { - hdb_lock_buffer[n] = 0; - pid = atoi(hdb_lock_buffer); - if (kill(pid, 0) == -1 && errno == ESRCH) { - /* pid no longer exists - remove the lock file */ - if (unlink(lock_file) == 0) { - close(fd); - syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)", - dev, pid); - continue; - } else - syslog(LOG_WARNING, "Couldn't remove stale lock on %s", - dev); - } else - syslog(LOG_NOTICE, "Device %s is locked by pid %d", - dev, pid); - } - close(fd); - } else - syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file); - free(lock_file); - lock_file = NULL; - return -1; - } - - sprintf(hdb_lock_buffer, "%10d\n", getpid()); - write(fd, hdb_lock_buffer, 11); - - close(fd); - return 0; -} - -/* - * unlock - remove our lockfile - */ -void -unlock() -{ - if (lock_file) { - unlink(lock_file); - free(lock_file); - lock_file = NULL; - } -} diff --git a/usr.sbin/pppd/upap.c b/usr.sbin/pppd/upap.c deleted file mode 100644 index af25a58..0000000 --- a/usr.sbin/pppd/upap.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * upap.c - User/Password Authentication Protocol. - * - * 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. - */ - -#ifndef lint -static char rcsid[] = "$FreeBSD$"; -#endif - -/* - * TODO: - */ - -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/time.h> -#include <syslog.h> - -#include "pppd.h" -#include "upap.h" - -/* - * Protocol entry points. - */ -static void upap_init(int); -static void upap_lowerup(int); -static void upap_lowerdown(int); -static void upap_input(int, u_char *, int); -static void upap_protrej(int); -static int upap_printpkt(u_char *, int, - void (*)(void *, char *, ...), void *); - -struct protent pap_protent = { - PPP_PAP, - upap_init, - upap_input, - upap_protrej, - upap_lowerup, - upap_lowerdown, - NULL, - NULL, - upap_printpkt, - NULL, - 1, - "PAP", - NULL, - NULL, - NULL -}; - -upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ - -static void upap_timeout(void *); -static void upap_reqtimeout(void *); -static void upap_rauthreq(upap_state *, u_char *, int, int); -static void upap_rauthack(upap_state *, u_char *, int, int); -static void upap_rauthnak(upap_state *, u_char *, int, int); -static void upap_sauthreq(upap_state *); -static void upap_sresp(upap_state *, int, int, char *, int); - - -/* - * upap_init - Initialize a UPAP unit. - */ -static void -upap_init(unit) - int unit; -{ - upap_state *u = &upap[unit]; - - u->us_unit = unit; - u->us_user = NULL; - u->us_userlen = 0; - u->us_passwd = NULL; - u->us_passwdlen = 0; - u->us_clientstate = UPAPCS_INITIAL; - u->us_serverstate = UPAPSS_INITIAL; - u->us_id = 0; - u->us_timeouttime = UPAP_DEFTIMEOUT; - u->us_maxtransmits = 10; - u->us_reqtimeout = UPAP_DEFREQTIME; -} - - -/* - * upap_authwithpeer - Authenticate us with our peer (start client). - * - * Set new state and send authenticate's. - */ -void -upap_authwithpeer(unit, user, password) - int unit; - char *user, *password; -{ - upap_state *u = &upap[unit]; - - /* Save the username and password we're given */ - u->us_user = user; - u->us_userlen = strlen(user); - u->us_passwd = password; - u->us_passwdlen = strlen(password); - u->us_transmits = 0; - - /* Lower layer up yet? */ - if (u->us_clientstate == UPAPCS_INITIAL || - u->us_clientstate == UPAPCS_PENDING) { - u->us_clientstate = UPAPCS_PENDING; - return; - } - - upap_sauthreq(u); /* Start protocol */ -} - - -/* - * upap_authpeer - Authenticate our peer (start server). - * - * Set new state. - */ -void -upap_authpeer(unit) - int unit; -{ - upap_state *u = &upap[unit]; - - /* Lower layer up yet? */ - if (u->us_serverstate == UPAPSS_INITIAL || - u->us_serverstate == UPAPSS_PENDING) { - u->us_serverstate = UPAPSS_PENDING; - return; - } - - u->us_serverstate = UPAPSS_LISTEN; - if (u->us_reqtimeout > 0) - TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); -} - - -/* - * upap_timeout - Retransmission timer for sending auth-reqs expired. - */ -static void -upap_timeout(arg) - void *arg; -{ - upap_state *u = (upap_state *) arg; - - if (u->us_clientstate != UPAPCS_AUTHREQ) - return; - - if (u->us_transmits >= u->us_maxtransmits) { - /* give up in disgust */ - syslog(LOG_ERR, "No response to PAP authenticate-requests"); - u->us_clientstate = UPAPCS_BADAUTH; - auth_withpeer_fail(u->us_unit, PPP_PAP); - return; - } - - upap_sauthreq(u); /* Send Authenticate-Request */ -} - - -/* - * upap_reqtimeout - Give up waiting for the peer to send an auth-req. - */ -static void -upap_reqtimeout(arg) - void *arg; -{ - upap_state *u = (upap_state *) arg; - - if (u->us_serverstate != UPAPSS_LISTEN) - return; /* huh?? */ - - auth_peer_fail(u->us_unit, PPP_PAP); - u->us_serverstate = UPAPSS_BADAUTH; -} - - -/* - * upap_lowerup - The lower layer is up. - * - * Start authenticating if pending. - */ -static void -upap_lowerup(unit) - int unit; -{ - upap_state *u = &upap[unit]; - - if (u->us_clientstate == UPAPCS_INITIAL) - u->us_clientstate = UPAPCS_CLOSED; - else if (u->us_clientstate == UPAPCS_PENDING) { - upap_sauthreq(u); /* send an auth-request */ - } - - if (u->us_serverstate == UPAPSS_INITIAL) - u->us_serverstate = UPAPSS_CLOSED; - else if (u->us_serverstate == UPAPSS_PENDING) { - u->us_serverstate = UPAPSS_LISTEN; - if (u->us_reqtimeout > 0) - TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); - } -} - - -/* - * upap_lowerdown - The lower layer is down. - * - * Cancel all timeouts. - */ -static void -upap_lowerdown(unit) - int unit; -{ - upap_state *u = &upap[unit]; - - if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ - UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ - if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) - UNTIMEOUT(upap_reqtimeout, u); - - u->us_clientstate = UPAPCS_INITIAL; - u->us_serverstate = UPAPSS_INITIAL; -} - - -/* - * upap_protrej - Peer doesn't speak this protocol. - * - * This shouldn't happen. In any case, pretend lower layer went down. - */ -static void -upap_protrej(unit) - int unit; -{ - upap_state *u = &upap[unit]; - - if (u->us_clientstate == UPAPCS_AUTHREQ) { - syslog(LOG_ERR, "PAP authentication failed due to protocol-reject"); - auth_withpeer_fail(unit, PPP_PAP); - } - if (u->us_serverstate == UPAPSS_LISTEN) { - syslog(LOG_ERR, "PAP authentication of peer failed (protocol-reject)"); - auth_peer_fail(unit, PPP_PAP); - } - upap_lowerdown(unit); -} - - -/* - * upap_input - Input UPAP packet. - */ -static void -upap_input(unit, inpacket, l) - int unit; - u_char *inpacket; - int l; -{ - upap_state *u = &upap[unit]; - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (l < UPAP_HEADERLEN) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < UPAP_HEADERLEN) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.")); - return; - } - if (len > l) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.")); - return; - } - len -= UPAP_HEADERLEN; - - /* - * Action depends on code. - */ - switch (code) { - case UPAP_AUTHREQ: - upap_rauthreq(u, inp, id, len); - break; - - case UPAP_AUTHACK: - upap_rauthack(u, inp, id, len); - break; - - case UPAP_AUTHNAK: - upap_rauthnak(u, inp, id, len); - break; - - default: /* XXX Need code reject */ - break; - } -} - - -/* - * upap_rauth - Receive Authenticate. - */ -static void -upap_rauthreq(u, inp, id, len) - upap_state *u; - u_char *inp; - int id; - int len; -{ - u_char ruserlen, rpasswdlen; - char *ruser, *rpasswd; - int retcode; - char *msg; - int msglen; - - UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.", id)); - - if (u->us_serverstate < UPAPSS_LISTEN) - return; - - /* - * If we receive a duplicate authenticate-request, we are - * supposed to return the same status as for the first request. - */ - if (u->us_serverstate == UPAPSS_OPEN) { - upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ - return; - } - if (u->us_serverstate == UPAPSS_BADAUTH) { - upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ - return; - } - - /* - * Parse user/passwd. - */ - if (len < sizeof (u_char)) { - UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.")); - return; - } - GETCHAR(ruserlen, inp); - len -= sizeof (u_char) + ruserlen + sizeof (u_char); - if (len < 0) { - UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.")); - return; - } - ruser = (char *) inp; - INCPTR(ruserlen, inp); - GETCHAR(rpasswdlen, inp); - if (len < rpasswdlen) { - UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.")); - return; - } - rpasswd = (char *) inp; - - /* - * Check the username and password given. - */ - retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, - rpasswdlen, &msg, &msglen); - BZERO(rpasswd, rpasswdlen); - - upap_sresp(u, retcode, id, msg, msglen); - - if (retcode == UPAP_AUTHACK) { - u->us_serverstate = UPAPSS_OPEN; - auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen); - } else { - u->us_serverstate = UPAPSS_BADAUTH; - auth_peer_fail(u->us_unit, PPP_PAP); - } - - if (u->us_reqtimeout > 0) - UNTIMEOUT(upap_reqtimeout, u); -} - - -/* - * upap_rauthack - Receive Authenticate-Ack. - */ -static void -upap_rauthack(u, inp, id, len) - upap_state *u; - u_char *inp; - int id; - int len; -{ - u_char msglen; - char *msg; - - UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d.", id)); - if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */ - return; - - /* - * Parse message. - */ - if (len < sizeof (u_char)) { - UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.")); - return; - } - GETCHAR(msglen, inp); - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - - u->us_clientstate = UPAPCS_OPEN; - - auth_withpeer_success(u->us_unit, PPP_PAP); -} - - -/* - * upap_rauthnak - Receive Authenticate-Nakk. - */ -static void -upap_rauthnak(u, inp, id, len) - upap_state *u; - u_char *inp; - int id; - int len; -{ - u_char msglen; - char *msg; - - UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d.", id)); - if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */ - return; - - /* - * Parse message. - */ - if (len < sizeof (u_char)) { - UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.")); - return; - } - GETCHAR(msglen, inp); - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - - u->us_clientstate = UPAPCS_BADAUTH; - - syslog(LOG_ERR, "PAP authentication failed"); - auth_withpeer_fail(u->us_unit, PPP_PAP); -} - - -/* - * upap_sauthreq - Send an Authenticate-Request. - */ -static void -upap_sauthreq(u) - upap_state *u; -{ - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + - u->us_userlen + u->us_passwdlen; - outp = outpacket_buf; - - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(UPAP_AUTHREQ, outp); - PUTCHAR(++u->us_id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(u->us_userlen, outp); - BCOPY(u->us_user, outp, u->us_userlen); - INCPTR(u->us_userlen, outp); - PUTCHAR(u->us_passwdlen, outp); - BCOPY(u->us_passwd, outp, u->us_passwdlen); - - output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); - - UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d.", u->us_id)); - - TIMEOUT(upap_timeout, u, u->us_timeouttime); - ++u->us_transmits; - u->us_clientstate = UPAPCS_AUTHREQ; -} - - -/* - * upap_sresp - Send a response (ack or nak). - */ -static void -upap_sresp(u, code, id, msg, msglen) - upap_state *u; - u_char code, id; - char *msg; - int msglen; -{ - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; - outp = outpacket_buf; - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(msglen, outp); - BCOPY(msg, outp, msglen); - output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); - - UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d.", code, id)); -} - -/* - * upap_printpkt - print the contents of a PAP packet. - */ -static char *upap_codenames[] = { - "AuthReq", "AuthAck", "AuthNak" -}; - -static int -upap_printpkt(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer)(void *, char *, ...); - void *arg; -{ - int code, id, len; - int mlen, ulen, wlen; - char *user, *pwd, *msg; - u_char *pstart; - - if (plen < UPAP_HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < UPAP_HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *)) - printer(arg, " %s", upap_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= UPAP_HEADERLEN; - switch (code) { - case UPAP_AUTHREQ: - if (len < 1) - break; - ulen = p[0]; - if (len < ulen + 2) - break; - wlen = p[ulen + 1]; - if (len < ulen + wlen + 2) - break; - user = (char *) (p + 1); - pwd = (char *) (p + ulen + 2); - p += ulen + wlen + 2; - len -= ulen + wlen + 2; - printer(arg, " user="); - print_string(user, ulen, printer, arg); - printer(arg, " password="); - print_string(pwd, wlen, printer, arg); - break; - case UPAP_AUTHACK: - case UPAP_AUTHNAK: - if (len < 1) - break; - mlen = p[0]; - if (len < mlen + 1) - break; - msg = (char *) (p + 1); - p += mlen + 1; - len -= mlen + 1; - printer(arg, " "); - print_string(msg, mlen, printer, arg); - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} diff --git a/usr.sbin/pppd/upap.h b/usr.sbin/pppd/upap.h deleted file mode 100644 index 82ce604..0000000 --- a/usr.sbin/pppd/upap.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * upap.h - User/Password Authentication Protocol definitions. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * Packet header = Code, id, length. - */ -#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) - - -/* - * UPAP codes. - */ -#define UPAP_AUTHREQ 1 /* Authenticate-Request */ -#define UPAP_AUTHACK 2 /* Authenticate-Ack */ -#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ - - -/* - * Each interface is described by upap structure. - */ -typedef struct upap_state { - int us_unit; /* Interface unit number */ - char *us_user; /* User */ - int us_userlen; /* User length */ - char *us_passwd; /* Password */ - int us_passwdlen; /* Password length */ - int us_clientstate; /* Client state */ - int us_serverstate; /* Server state */ - u_char us_id; /* Current id */ - int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ - int us_transmits; /* Number of auth-reqs sent */ - int us_maxtransmits; /* Maximum number of auth-reqs to send */ - int us_reqtimeout; /* Time to wait for auth-req from peer */ -} upap_state; - - -/* - * Client states. - */ -#define UPAPCS_INITIAL 0 /* Connection down */ -#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ -#define UPAPCS_OPEN 4 /* We've received an Ack */ -#define UPAPCS_BADAUTH 5 /* We've received a Nak */ - -/* - * Server states. - */ -#define UPAPSS_INITIAL 0 /* Connection down */ -#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ -#define UPAPSS_OPEN 4 /* We've sent an Ack */ -#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ - - -/* - * Timeouts. - */ -#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ -#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ - -extern upap_state upap[]; - -void upap_authwithpeer(int, char *, char *); -void upap_authpeer(int); - -extern struct protent pap_protent; |