From 2f1b9304ac4ba89a2dcb6047cb584a5603a33987 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 16 Aug 2001 20:42:09 +0000 Subject: 2001-08-16 Mike Siers * Update of PPPD to 2.3.11 from 2.3.5 and addition of an example application. Mike's notes on the modifications: - renamed error() function because of namespace problems - removed calls to the exit() funciton - removed extra files from the pppd source directory - defined pppd task constant values in rtemspppd.h - modifyied example code to get actual tick per second value - placed the pppd 2.3.11 man page file (pppd.8) into the pppd directory * pppd/cbcp.c, pppd/cbcp.h, pppd/main.c, pppd/ppp_tty.c, pppd/pppmain.c, pppd/rtems-ppp.c, pppd/rtems-ppp.c: Deleted. * pppd/pppd.8, pppd/rtemsmain.c, pppd/rtemspppd.c, pppd/rtemspppd.h, pppd/sys-rtems.c, pppd/utils.c, pppd/example/Makefile, pppd/example/README, pppd/example/init.c, pppd/example/netconfig.h, pppd/example/ppp.conf, pppd/example/pppdapp.c, pppd/example/system.h: New files. * modem/ppp_tty.c, net/if_ppp.h, pppd/Makefile.am, pppd/README, pppd/STATUS, pppd/auth.c, pppd/ccp.c, pppd/ccp.h, pppd/chap.c, pppd/chap.h, pppd/chap_ms.c, pppd/chap_ms.h, pppd/chat.c, pppd/demand.c, pppd/fsm.c, pppd/fsm.h, pppd/ipcp.c, pppd/ipcp.h, pppd/ipxcp.c, pppd/ipxcp.h, pppd/lcp.c, pppd/lcp.h, pppd/magic.c, pppd/magic.h, pppd/options.c, pppd/patchlevel.h, pppd/pathnames.h, pppd/pppd.h, pppd/upap.c, pppd/upap.h: Modified. --- c/src/exec/libnetworking/ChangeLog | 26 + c/src/exec/libnetworking/net/if_ppp.h | 1 + c/src/libnetworking/ChangeLog | 26 + c/src/libnetworking/modem/ppp_tty.c | 15 +- c/src/libnetworking/net/if_ppp.h | 1 + c/src/libnetworking/pppd/Makefile.am | 35 +- c/src/libnetworking/pppd/README | 56 +- c/src/libnetworking/pppd/STATUS | 27 +- c/src/libnetworking/pppd/auth.c | 733 ++++++++---- c/src/libnetworking/pppd/cbcp.c | 431 ------- c/src/libnetworking/pppd/cbcp.h | 26 - c/src/libnetworking/pppd/ccp.c | 194 +++- c/src/libnetworking/pppd/ccp.h | 12 +- c/src/libnetworking/pppd/chap.c | 122 +- c/src/libnetworking/pppd/chap.h | 4 +- c/src/libnetworking/pppd/chap_ms.c | 47 +- c/src/libnetworking/pppd/chat.c | 146 +-- c/src/libnetworking/pppd/demand.c | 9 +- c/src/libnetworking/pppd/example/Makefile | 45 + c/src/libnetworking/pppd/example/README | 6 + c/src/libnetworking/pppd/example/init.c | 24 + c/src/libnetworking/pppd/example/netconfig.h | 37 + c/src/libnetworking/pppd/example/ppp.conf | 27 + c/src/libnetworking/pppd/example/pppdapp.c | 146 +++ c/src/libnetworking/pppd/example/system.h | 42 + c/src/libnetworking/pppd/fsm.c | 78 +- c/src/libnetworking/pppd/fsm.h | 2 +- c/src/libnetworking/pppd/ipcp.c | 546 ++++++--- c/src/libnetworking/pppd/ipcp.h | 25 +- c/src/libnetworking/pppd/ipxcp.c | 298 +++-- c/src/libnetworking/pppd/ipxcp.h | 24 +- c/src/libnetworking/pppd/lcp.c | 269 +++-- c/src/libnetworking/pppd/lcp.h | 26 +- c/src/libnetworking/pppd/magic.c | 11 +- c/src/libnetworking/pppd/main.c | 1284 --------------------- c/src/libnetworking/pppd/options.c | 1570 ++++++++++++++++++++++---- c/src/libnetworking/pppd/patchlevel.h | 4 +- c/src/libnetworking/pppd/pathnames.h | 39 +- c/src/libnetworking/pppd/ppp_tty.c | 1080 ------------------ c/src/libnetworking/pppd/pppd.8 | 1480 ++++++++++++++++++++++++ c/src/libnetworking/pppd/pppd.h | 377 +++++-- c/src/libnetworking/pppd/pppmain.c | 1314 --------------------- c/src/libnetworking/pppd/rtems-ppp.c | 1521 ------------------------- c/src/libnetworking/pppd/rtemsmain.c | 903 +++++++++++++++ c/src/libnetworking/pppd/rtemspppd.c | 173 +++ c/src/libnetworking/pppd/rtemspppd.h | 38 + c/src/libnetworking/pppd/sys-rtems.c | 1322 ++++++++++++++++++++++ c/src/libnetworking/pppd/upap.c | 121 +- c/src/libnetworking/pppd/upap.h | 2 +- c/src/libnetworking/pppd/utils.c | 872 ++++++++++++++ 50 files changed, 8520 insertions(+), 7097 deletions(-) delete mode 100644 c/src/libnetworking/pppd/cbcp.c delete mode 100644 c/src/libnetworking/pppd/cbcp.h create mode 100644 c/src/libnetworking/pppd/example/Makefile create mode 100644 c/src/libnetworking/pppd/example/README create mode 100644 c/src/libnetworking/pppd/example/init.c create mode 100644 c/src/libnetworking/pppd/example/netconfig.h create mode 100644 c/src/libnetworking/pppd/example/ppp.conf create mode 100644 c/src/libnetworking/pppd/example/pppdapp.c create mode 100644 c/src/libnetworking/pppd/example/system.h delete mode 100644 c/src/libnetworking/pppd/main.c delete mode 100644 c/src/libnetworking/pppd/ppp_tty.c create mode 100644 c/src/libnetworking/pppd/pppd.8 delete mode 100644 c/src/libnetworking/pppd/pppmain.c delete mode 100644 c/src/libnetworking/pppd/rtems-ppp.c create mode 100644 c/src/libnetworking/pppd/rtemsmain.c create mode 100644 c/src/libnetworking/pppd/rtemspppd.c create mode 100644 c/src/libnetworking/pppd/rtemspppd.h create mode 100644 c/src/libnetworking/pppd/sys-rtems.c create mode 100644 c/src/libnetworking/pppd/utils.c (limited to 'c') diff --git a/c/src/exec/libnetworking/ChangeLog b/c/src/exec/libnetworking/ChangeLog index 610e6c2a31..953d9eaf5a 100644 --- a/c/src/exec/libnetworking/ChangeLog +++ b/c/src/exec/libnetworking/ChangeLog @@ -1,3 +1,29 @@ +2001-08-16 Mike Siers + + * Update of PPPD to 2.3.11 from 2.3.5 and addition of an example + application. Mike's notes on the modifications: + - renamed error() function because of namespace problems + - removed calls to the exit() funciton + - removed extra files from the pppd source directory + - defined pppd task constant values in rtemspppd.h + - modifyied example code to get actual tick per second value + - placed the pppd 2.3.11 man page file (pppd.8) into the pppd + directory + * pppd/cbcp.c, pppd/cbcp.h, pppd/main.c, pppd/ppp_tty.c, + pppd/pppmain.c, pppd/rtems-ppp.c, pppd/rtems-ppp.c: Deleted. + * pppd/pppd.8, pppd/rtemsmain.c, pppd/rtemspppd.c, pppd/rtemspppd.h, + pppd/sys-rtems.c, pppd/utils.c, pppd/example/Makefile, + pppd/example/README, pppd/example/init.c, pppd/example/netconfig.h, + pppd/example/ppp.conf, pppd/example/pppdapp.c, pppd/example/system.h: + New files. + * modem/ppp_tty.c, net/if_ppp.h, pppd/Makefile.am, pppd/README, + pppd/STATUS, pppd/auth.c, pppd/ccp.c, pppd/ccp.h, pppd/chap.c, + pppd/chap.h, pppd/chap_ms.c, pppd/chap_ms.h, pppd/chat.c, + pppd/demand.c, pppd/fsm.c, pppd/fsm.h, pppd/ipcp.c, pppd/ipcp.h, + pppd/ipxcp.c, pppd/ipxcp.h, pppd/lcp.c, pppd/lcp.h, pppd/magic.c, + pppd/magic.h, pppd/options.c, pppd/patchlevel.h, + pppd/pathnames.h, pppd/pppd.h, pppd/upap.c, pppd/upap.h: Modified. + 2001-08-16 Joel Sherrill * rtems_telnetd/.cvsignore: New file. diff --git a/c/src/exec/libnetworking/net/if_ppp.h b/c/src/exec/libnetworking/net/if_ppp.h index 9322f2e13b..0c9959b5c8 100644 --- a/c/src/exec/libnetworking/net/if_ppp.h +++ b/c/src/exec/libnetworking/net/if_ppp.h @@ -38,6 +38,7 @@ #define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ #define SC_LOG_RAWIN 0x00080000 /* log all chars received */ #define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_SYNC 0x00200000 /* synchrounous HDLC */ #define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ #define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ #define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ diff --git a/c/src/libnetworking/ChangeLog b/c/src/libnetworking/ChangeLog index 610e6c2a31..953d9eaf5a 100644 --- a/c/src/libnetworking/ChangeLog +++ b/c/src/libnetworking/ChangeLog @@ -1,3 +1,29 @@ +2001-08-16 Mike Siers + + * Update of PPPD to 2.3.11 from 2.3.5 and addition of an example + application. Mike's notes on the modifications: + - renamed error() function because of namespace problems + - removed calls to the exit() funciton + - removed extra files from the pppd source directory + - defined pppd task constant values in rtemspppd.h + - modifyied example code to get actual tick per second value + - placed the pppd 2.3.11 man page file (pppd.8) into the pppd + directory + * pppd/cbcp.c, pppd/cbcp.h, pppd/main.c, pppd/ppp_tty.c, + pppd/pppmain.c, pppd/rtems-ppp.c, pppd/rtems-ppp.c: Deleted. + * pppd/pppd.8, pppd/rtemsmain.c, pppd/rtemspppd.c, pppd/rtemspppd.h, + pppd/sys-rtems.c, pppd/utils.c, pppd/example/Makefile, + pppd/example/README, pppd/example/init.c, pppd/example/netconfig.h, + pppd/example/ppp.conf, pppd/example/pppdapp.c, pppd/example/system.h: + New files. + * modem/ppp_tty.c, net/if_ppp.h, pppd/Makefile.am, pppd/README, + pppd/STATUS, pppd/auth.c, pppd/ccp.c, pppd/ccp.h, pppd/chap.c, + pppd/chap.h, pppd/chap_ms.c, pppd/chap_ms.h, pppd/chat.c, + pppd/demand.c, pppd/fsm.c, pppd/fsm.h, pppd/ipcp.c, pppd/ipcp.h, + pppd/ipxcp.c, pppd/ipxcp.h, pppd/lcp.c, pppd/lcp.h, pppd/magic.c, + pppd/magic.h, pppd/options.c, pppd/patchlevel.h, + pppd/pathnames.h, pppd/pppd.h, pppd/upap.c, pppd/upap.h: Modified. + 2001-08-16 Joel Sherrill * rtems_telnetd/.cvsignore: New file. diff --git a/c/src/libnetworking/modem/ppp_tty.c b/c/src/libnetworking/modem/ppp_tty.c index 27fff62a29..e3ca3f4a41 100644 --- a/c/src/libnetworking/modem/ppp_tty.c +++ b/c/src/libnetworking/modem/ppp_tty.c @@ -433,13 +433,13 @@ int ppptioctl(struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args) { - struct ppp_softc *sc=tty->t_sc; - int cmd; - caddr_t data; - int error=RTEMS_SUCCESSFUL; + int error = RTEMS_SUCCESSFUL; + struct ppp_softc *sc = tty->t_sc; + int cmd; + caddr_t data; - data=args->buffer; cmd=args->command; + data=args->buffer; switch (cmd) { case RTEMS_IO_GET_ATTRIBUTES: @@ -447,8 +447,11 @@ ppptioctl(struct rtems_termios_tty *tty, case RTEMS_IO_TCDRAIN: case TIOCGETD: case TIOCSETD: - return RTEMS_UNSATISFIED; + case RTEMS_IO_SNDWAKEUP: + case RTEMS_IO_RCVWAKEUP: + error = rtems_termios_ioctl(args); break; + case PPPIOCSASYNCMAP: sc->sc_asyncmap[0] = *(u_int *)data; break; diff --git a/c/src/libnetworking/net/if_ppp.h b/c/src/libnetworking/net/if_ppp.h index 9322f2e13b..0c9959b5c8 100644 --- a/c/src/libnetworking/net/if_ppp.h +++ b/c/src/libnetworking/net/if_ppp.h @@ -38,6 +38,7 @@ #define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ #define SC_LOG_RAWIN 0x00080000 /* log all chars received */ #define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_SYNC 0x00200000 /* synchrounous HDLC */ #define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ #define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ #define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ diff --git a/c/src/libnetworking/pppd/Makefile.am b/c/src/libnetworking/pppd/Makefile.am index 836d2ab110..9aab295eb3 100644 --- a/c/src/libnetworking/pppd/Makefile.am +++ b/c/src/libnetworking/pppd/Makefile.am @@ -4,13 +4,13 @@ AUTOMAKE_OPTIONS = foreign 1.4 + + + LIBNAME = lib.a LIB = $(ARCH)/$(LIBNAME) -# renamed main.c to pppmain.c -C_FILES = auth.c cbcp.c ccp.c chap.c chap_ms.c chat.c demand.c fsm.c ipcp.c \ - ipxcp.c lcp.c magic.c options.c upap.c md4.c md5.c rtems-ppp.c \ - pppmain.c +C_FILES = auth.c ccp.c chap.c chap_ms.c chat.c demand.c fsm.c ipcp.c lcp.c magic.c options.c upap.c md4.c md5.c utils.c sys-rtems.c rtemsmain.c rtemspppd.c C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) OBJS = $(C_O_FILES) @@ -23,24 +23,25 @@ include $(top_srcdir)/../../../automake/lib.am # Add local stuff here using += # -# DEFINES += -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS -DDIAGNOSTIC \ -# -DBOOTP_COMPAT - $(LIB): $(OBJS) $(make-library) -EXTRA_FILES = modem_example/16550.h modem_example/README \ - modem_example/modem.c modem_example/modem.h modem_example/ppp.c \ - modem_example/ppp.h modem_example/pppcompress.c - -all-local: $(ARCH) $(OBJS) $(LIB) +all-local: $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(LIB) .PRECIOUS: $(LIB) -EXTRA_DIST = README STATUS auth.c cbcp.c cbcp.h ccp.c ccp.h chap.c chap.h \ - chap_ms.c chap_ms.h chat.c demand.c fsm.c fsm.h ipcp.c ipcp.h ipxcp.c \ - ipxcp.h lcp.c lcp.h magic.c magic.h main.c md4.c md4.h md5.c md5.h \ - options.c patchlevel.h pathnames.h ppp_tty.c pppd.h rtems-ppp.c upap.c \ - upap.h pppmain.c $(EXTRA_FILES) +EXTRA_DIST = auth.c ccp.c ccp.h chap.c chap.h chap_ms.c chap_ms.h \ +chat.c demand.c fsm.c fsm.h ipcp.c ipcp.h ipxcp.c ipxcp.h \ +lcp.c lcp.h magic.c magic.h md4.c md4.h md5.c md5.h options.c \ +patchlevel.h pathnames.h pppd.h rtemsmain.c rtemspppd.c rtemspppd.h \ +sys-rtems.c upap.c upap.h utils.c + +include_HEADERS = rtemspppd.h + + +PREINSTALL_FILES += $(PROJECT_INCLUDE) $(include_HEADERS:%=$(PROJECT_INCLUDE)/%) + +$(PROJECT_INCLUDE)/%.h: %.h + $(INSTALL_DATA) $< $@ include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/libnetworking/pppd/README b/c/src/libnetworking/pppd/README index 8002d3e280..0615100344 100644 --- a/c/src/libnetworking/pppd/README +++ b/c/src/libnetworking/pppd/README @@ -2,57 +2,19 @@ # $Id$ # -This directory contains a port of ppp-2.3.5. The official site for +This directory contains a port of ppp-2.3.11. The official site for the original source for this PPP implementation is: ftp://cs.anu.edu.au/pub/software/ppp -NOTE: As of 11/30/1999, the current version of this source is 2.3.10. - -The port was performed by Tomasz Domin of ComArch SA -and has only been tested on the mpc823. The modem driver should -work with minor modifications on other systems. -================================================================= -Some comments: - -+ "SetStatusInfo is a function which displays given message on - bottom side of the screen." - - The issue of how to deal with SetStatusInfo in a generic, portable - fashion is still open. - -+ "Dialer returns positive integer when an error occurs, and negative one - which is parsed from modem aswer, when connection is done (for example - -28000 if connection speed is 28000 baud ...)" - -+ PPP_User/PPP_Password - "When this field is set, it is sent to the server when there is need - to login .... - When it is blank - it is using other method of authentification ... or - none ... - PPP_Password is also used in CHAT and PAP - because there is no - configuration files in RTEMS ..." - - This falls into the general question of how to generally configure this. - -+ ConnectionStatus - - This is the method of synchronization between pppd task and others. - ConnectionStatus field is set by pppd - when connection occurs it`s state - is set to Connected. WantConnection is set by client application (and - the appriopriate event is sent then) so pppd knows what user wants to do ... - -+ Around line 270 of main.c, there is code to change the default - nameserver... why? - - Becouse in my application user can change it anytime ... - without need of - rebooting the system - When PPP connection is configured there is needed additional info about - nameservers - PPP layer cant discover them itself - - - - +================================================================ +History +The original port was of 2.3.5 by Tomasz Domin of +ComArch SA and was initially only tested on the mpc823. He +provided the modem driver as well. +The port was updated to 2.3.11 by Mike Siers +who added an example test. +================================================================= diff --git a/c/src/libnetworking/pppd/STATUS b/c/src/libnetworking/pppd/STATUS index 0e4980cbbc..3bcf2e205b 100644 --- a/c/src/libnetworking/pppd/STATUS +++ b/c/src/libnetworking/pppd/STATUS @@ -2,28 +2,5 @@ # $Id$ # -Overall, this code should still be considered in its early stages. It -works but has some distance to go before it is fully documented and -easily configurable. - -+ Compare the code to the original 2.3.5 and eliminate spurious changes. - -+ Update the code to 2.3.10. - -+ Eliminate items specific to Tomasz' system. In particular, the - code reports status and gets configuration information in a system - specific manner. main.c is particularly guilty of this although - other files suffer from this also. - -+ Find comments in Polish and get Tomasz to translate them. :) - (DONE but not sure if completely - Radzislaw Galler ) - -+ Add netdemo showing configuration and initialization. - -+ Get feature list. - -+ Document dialer setup. - -+ Only modem driver is system specific so there is the possibility - that shareable code exists in it. +This file needs to be redone to reflect tasks left after the 2.3.11 +update. diff --git a/c/src/libnetworking/pppd/auth.c b/c/src/libnetworking/pppd/auth.c index f5cff9ac3d..f08a89a0c1 100644 --- a/c/src/libnetworking/pppd/auth.c +++ b/c/src/libnetworking/pppd/auth.c @@ -32,21 +32,18 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" #include #include -#include +#include #include -#include #include +#include #include #include #include #include - #include #if defined(_PATH_LASTLOG) && defined(_linux_) #include @@ -55,7 +52,17 @@ #include #include #include -/* #include */ + +#ifdef USE_PAM +#include +#endif + +#ifdef HAS_SHADOW +#include +#ifndef PW_PPP +#define PW_PPP PW_LOGIN +#endif +#endif #include "pppd.h" #include "fsm.h" @@ -68,20 +75,7 @@ #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 +static const char rcsid[] = RCSID; /* The name by which the peer authenticated itself to us. */ char peer_authname[MAXNAMELEN]; @@ -89,14 +83,15 @@ 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; +/* List of addresses which the peer may use. */ +static struct permitted_ip *addresses[NUM_PPP]; -/* Set if we have run the /etc/ppp/auth-up script. */ -static int did_authup; +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; -/* List of addresses which the peer may use. */ -static struct wordlist *addresses[NUM_PPP]; +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; /* Number of network protocols which we have opened. */ static int num_np_open; @@ -107,6 +102,55 @@ static int num_np_up; /* Set if we got the contents of passwd[] from the pap-secrets file. */ static int passwd_from_file; +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook for a link status */ +void (*auth_linkup_hook)__P((void)) = NULL; +void (*auth_linkdown_hook)__P((void)) = NULL; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) __P((struct ppp_idle *)) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) __P((void)) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts)) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) __P((void)) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; + +/* + * This is used to ensure that we don't start an auth-up/down + * script while one is already running. + */ +enum script_state { + s_down, + s_up +}; + +static enum script_state auth_state = s_down; +static enum script_state auth_script_state = s_down; + +/* + * Option variables. + */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ + /* Bits in auth_pending[] */ #define PAP_WITHPEER 1 #define PAP_PEER 2 @@ -120,18 +164,70 @@ extern char *crypt __P((const char *, const char *)); static void network_phase __P((int)); static void check_idle __P((void *)); static void connect_time_expired __P((void *)); -static int plogin __P((char *, char *, char **, int *)); -static void plogout __P((void)); static int null_login __P((int)); static int get_pap_passwd __P((char *)); -static int have_pap_secret __P((void)); -static int have_chap_secret __P((char *, char *, u_int32_t)); -static int ip_addr_check __P((u_int32_t, struct wordlist *)); -static int scan_authfile __P((FILE *, char *, char *, u_int32_t, char *, - struct wordlist **, char *)); +static int have_pap_secret __P((int *)); +static int have_chap_secret __P((char *, char *, int, int *)); +static int ip_addr_check __P((u_int32_t, struct permitted_ip *)); static void free_wordlist __P((struct wordlist *)); -static void auth_script __P((char *)); -static void set_allowed_addrs __P((int, struct wordlist *)); +static void auth_script __P((enum script_state s)); +static void set_allowed_addrs __P((int, struct wordlist *, struct wordlist *)); + + +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", 1 }, + { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", 1 }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", 1 }, + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, + { "user", o_string, user, + "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + { "auth", o_bool, &auth_required, + "Require authentication from peer", 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, + { "login", o_bool, &uselogin, + "Use system password database for PAP", 1 }, + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, +/* Removed for RTEMS PORT + { "+ua", o_special, setupapfile, + "Get PAP user and password from file" }, +*/ + { "password", o_string, passwd, + "Password for authenticating us to the peer", OPT_STATIC, + NULL, MAXSECRETLEN }, +/* Removed for RTEMS_PORT + { "privgroup", o_special, privgroup, + "Allow group members to use privileged options", OPT_PRIV }, + { "allow-ip", o_special, set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV }, +*/ + { NULL } +}; /* * An Open on LCP has requested a change from Dead to Establish phase. @@ -153,10 +249,11 @@ link_terminated(unit) { if (phase == PHASE_DEAD) return; - if (logged_in) - plogout(); - phase = PHASE_DEAD; - syslog(LOG_NOTICE, "Connection terminated."); + if (pap_logout_hook) { + pap_logout_hook(); + } + new_phase(PHASE_DEAD); + notice("Connection terminated."); } /* @@ -169,7 +266,11 @@ link_down(unit) int i; struct protent *protp; - did_authup = 0; + auth_state = s_down; + if (auth_script_state == s_up) { + update_link_stats(unit); + auth_script(s_down); + } for (i = 0; (protp = protocols[i]) != NULL; ++i) { if (!protp->enabled_flag) continue; @@ -181,7 +282,7 @@ link_down(unit) num_np_open = 0; num_np_up = 0; if (phase != PHASE_DEAD) - phase = PHASE_TERMINATE; + new_phase(PHASE_TERMINATE); } /* @@ -210,16 +311,22 @@ link_established(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 we have some address(es) it can use without auth, fine, + * otherwise 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)) { + if (noauth_addrs != NULL) { + set_allowed_addrs(unit, noauth_addrs, NULL); + } else if (!wo->neg_upap || !null_login(unit)) { + warn("peer refused to authenticate: terminating link"); lcp_close(unit, "peer refused to authenticate"); + status = EXIT_PEER_AUTH_FAILED; return; } } - phase = PHASE_AUTHENTICATE; + new_phase(PHASE_AUTHENTICATE); auth = 0; if (go->neg_chap) { ChapAuthPeer(unit, our_name, go->chap_mdtype); @@ -234,7 +341,8 @@ link_established(unit) } else if (ho->neg_upap) { if (passwd[0] == 0) { passwd_from_file = 1; - get_pap_passwd(passwd); + if (!get_pap_passwd(passwd)) + error("No secret found for PAP login"); } upap_authwithpeer(unit, user, passwd); auth |= PAP_WITHPEER; @@ -252,16 +360,14 @@ static void network_phase(unit) int unit; { - int i; - struct protent *protp; +#ifdef CBCP_SUPPORT lcp_options *go = &lcp_gotoptions[unit]; +#endif - /* - * 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; + /* always run the auth-up script */ + auth_state = s_up; + if (auth_script_state == s_down) { + auth_script(s_up); } #ifdef CBCP_SUPPORT @@ -269,18 +375,34 @@ network_phase(unit) * If we negotiated callback, do it now. */ if (go->neg_cbcp) { - phase = PHASE_CALLBACK; + new_phase(PHASE_CALLBACK); (*cbcp_protent.open)(unit); return; } #endif - phase = PHASE_NETWORK; + /* + * Process extra options from the secrets file + */ + if (extra_options) { + options_from_list(extra_options, 1); + free_wordlist(extra_options); + extra_options = 0; + } + start_networks(); +} + +void +start_networks() +{ + int i; + struct protent *protp; + new_phase(PHASE_NETWORK); for (i = 0; (protp = protocols[i]) != NULL; ++i) if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { - (*protp->open)(unit); + (*protp->open)(0); if (protp->protocol != PPP_CCP) ++num_np_open; } @@ -301,6 +423,7 @@ auth_peer_fail(unit, protocol) * Authentication failure: take the link down */ lcp_close(unit, "Authentication failed"); + status = EXIT_PEER_AUTH_FAILED; } /* @@ -322,8 +445,7 @@ auth_peer_success(unit, protocol, name, namelen) bit = PAP_PEER; break; default: - syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x", - protocol); + warn("auth_peer_success: unknown protocol %x", protocol); return; } @@ -334,6 +456,7 @@ auth_peer_success(unit, protocol, name, namelen) namelen = sizeof(peer_authname) - 1; BCOPY(name, peer_authname, namelen); peer_authname[namelen] = 0; + /* * If there is no more authentication still to be done, * proceed to the network (or callback) phase. @@ -353,9 +476,12 @@ auth_withpeer_fail(unit, protocol) 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. + * Some servers keep sending CHAP challenges, but there + * is no point in persisting without any way to get updated + * authentication secrets. */ + lcp_close(unit, "Failed to authenticate ourselves to peer"); + status = EXIT_AUTH_TOPEER_FAILED; } /* @@ -377,7 +503,7 @@ auth_withpeer_success(unit, protocol) bit = PAP_WITHPEER; break; default: - + warn("auth_withpeer_success: unknown protocol %x", protocol); bit = 0; } @@ -397,14 +523,22 @@ void np_up(unit, proto) int unit, proto; { + int tlim; + if (num_np_up == 0) { /* * At this point we consider that the link has come up successfully. */ - need_holdoff = 0; + status = EXIT_OK; + unsuccess = 0; + new_phase(PHASE_RUNNING); - if (idle_time_limit > 0) - TIMEOUT(check_idle, NULL, idle_time_limit); + if (idle_time_hook != 0) + tlim = (*idle_time_hook)(NULL); + else + tlim = idle_time_limit; + if (tlim > 0) + TIMEOUT(check_idle, NULL, tlim); /* * Set a timeout to close the connection once the maximum @@ -412,12 +546,6 @@ np_up(unit, proto) */ if (maxconnect > 0) TIMEOUT(connect_time_expired, 0, maxconnect); - - /* - * Detach now, if the updetach option was given. - */ - if (nodetach == -1) - detach(); } ++num_np_up; } @@ -429,8 +557,9 @@ void np_down(unit, proto) int unit, proto; { - if (--num_np_up == 0 && idle_time_limit > 0) { + if (--num_np_up == 0) { UNTIMEOUT(check_idle, NULL); + new_phase(PHASE_NETWORK); } } @@ -453,20 +582,28 @@ np_finished(unit, proto) */ static void check_idle(arg) - void *arg; + void *arg; { struct ppp_idle idle; time_t itime; + int tlim; if (!get_idle_time(0, &idle)) return; - itime = MIN(idle.xmit_idle, idle.recv_idle); - if (itime >= idle_time_limit) { + if (idle_time_hook != 0) { + tlim = idle_time_hook(&idle); + } else { + itime = MIN(idle.xmit_idle, idle.recv_idle); + tlim = idle_time_limit - itime; + } + if (tlim <= 0) { /* link is idle: shut it down. */ - syslog(LOG_INFO, "Terminating connection due to lack of activity."); + notice("Terminating connection due to lack of activity."); lcp_close(0, "Link inactive"); + need_holdoff = 0; + status = EXIT_IDLE_TIMEOUT; } else { - TIMEOUT(check_idle, NULL, idle_time_limit - itime); + TIMEOUT(check_idle, NULL, tlim); } } @@ -477,70 +614,82 @@ static void connect_time_expired(arg) void *arg; { - syslog(LOG_INFO, "Connect time expired"); + info("Connect time expired"); lcp_close(0, "Connect time expired"); /* Close connection */ + status = EXIT_CONNECT_TIME; } /* * auth_check_options - called to check authentication options. */ -void +int auth_check_options() { lcp_options *wo = &lcp_wantoptions[0]; + int status = 1; int can_auth; - ipcp_options *ipwo = &ipcp_wantoptions[0]; - u_int32_t remote; + int lacks_ip; /* Default our_name to hostname, and user to our_name */ if (our_name[0] == 0 || usehostname) - strcpy(our_name, hostname); + strlcpy(our_name, hostname, sizeof(our_name)); if (user[0] == 0) - strcpy(user, our_name); + strlcpy(user, our_name, sizeof(user)); + + /* + * If we have a default route, require the peer to authenticate + * unless the noauth option was given or the real user is root. + */ + if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { + printf("auth_check_options: turning on\n"); + auth_required = 1; + default_auth = 1; + } /* 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; + if (auth_required) { + if (!wo->neg_chap && !wo->neg_upap) { + wo->neg_chap = 1; + wo->neg_upap = 1; + } + } else { + wo->neg_chap = 0; + wo->neg_upap = 0; } /* * Check whether we have appropriate secrets to use * to authenticate the peer. */ - can_auth = wo->neg_upap && (uselogin || have_pap_secret()); + lacks_ip = 0; + can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); if (!can_auth && wo->neg_chap) { - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - can_auth = have_chap_secret(remote_name, our_name, remote); + can_auth = have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, &lacks_ip); } - 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); + if (auth_required && !can_auth && noauth_addrs == NULL) { + if (default_auth) { + option_error( +"By default the remote system is required to authenticate itself"); + option_error( +"(because this system has a default route to the internet)"); + } else if (explicit_remote) + option_error( +"The remote system (%s) is required to authenticate itself", + remote_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); - } + option_error( +"The remote system is required to authenticate itself"); + option_error( +"but I couldn't find any suitable secret (password) for it to use to do so."); + if (lacks_ip) + option_error( +"(None of the available passwords would let it use an IP address.)"); + + status = 0; } + return ( status ); } /* @@ -554,18 +703,18 @@ auth_reset(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_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); + && (passwd[0] != 0 + || have_chap_secret(user, (explicit_remote? remote_name: NULL), + 0, NULL)); - if (go->neg_upap && !uselogin && !have_pap_secret()) + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) go->neg_upap = 0; if (go->neg_chap) { - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - if (!have_chap_secret(remote_name, our_name, remote)) + if (!have_chap_secret((explicit_remote? remote_name: NULL), + our_name, 1, NULL)) go->neg_chap = 0; } } @@ -582,55 +731,24 @@ auth_reset(unit) * In either case, msg points to an appropriate message. */ int -check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) +check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) int unit; char *auser; int userlen; char *apasswd; int passwdlen; char **msg; - int *msglen; { + int ret = (int)UPAP_AUTHNAK; + if (( userlen == 0 ) && ( passwdlen == 0 )) { + ret = (int)UPAP_AUTHACK; + } + printf("check_passwd: %d\n", ret); - return UPAP_AUTHNAK; -} - - -/* - * 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. - */ - -static int -plogin(user, passwd, msg, msglen) - char *user; - char *passwd; - char **msg; - int *msglen; -{ - syslog(LOG_INFO, "user %s logged in", user); - logged_in = TRUE; - - return (UPAP_AUTHACK); -} - -/* - * plogout - Logout the user. - */ -static void -plogout() -{ - - logged_in = FALSE; + return ret; } - /* * null_login - Check if a username of "" and a password of "" are * acceptable, and iff so, set the list of acceptable IP addresses @@ -640,7 +758,7 @@ static int null_login(unit) int unit; { - return 1; + return 0; } @@ -648,20 +766,22 @@ null_login(unit) * 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. + * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). */ - static int get_pap_passwd(passwd) char *passwd; { -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus *stat; - stat=LockSTBSystemParam(); - strncpy(passwd, stat->PPP_Password, MAXSECRETLEN); - UnlockSTBSystemParam(); -#endif - return 1; + int ret = (int)0; + + /* + * Check whether a plugin wants to supply this. + */ + if (pap_passwd_hook) { + ret = (*pap_passwd_hook)(user, passwd); + } + + return ( ret ); } @@ -670,9 +790,18 @@ get_pap_passwd(passwd) * secrets that we could possibly use for authenticating the peer. */ static int -have_pap_secret() +have_pap_secret(lacks_ipp) + int *lacks_ipp; { - return 1; + int ret = (int)0; + + /* let the plugin decide, if there is one */ + printf("have_pap_secret:\n"); + if (pap_check_hook) { + ret = (*pap_check_hook)(); + } + + return ( ret ); } @@ -683,13 +812,13 @@ have_pap_secret() * know the identity yet. */ static int -have_chap_secret(client, server, remote) +have_chap_secret(client, server, need_ip, lacks_ipp) char *client; char *server; - u_int32_t remote; + int need_ip; + int *lacks_ipp; { - - return 1; + return 0; } @@ -699,37 +828,178 @@ have_chap_secret(client, server, remote) * (We could be either client or server). */ int -get_secret(unit, client, server, secret, secret_len, save_addrs) +get_secret(unit, client, server, secret, secret_len, am_server) int unit; char *client; char *server; char *secret; int *secret_len; - int save_addrs; + int am_server; { -#if 0 -/* XXX PPPConfiguration */ int len; - GlobalSystemStatus *stat; - stat=LockSTBSystemParam(); - len=strlen(stat->PPP_Password); - strcpy( secret,stat->PPP_Password); - UnlockSTBSystemParam(); + char secbuf[MAXWORDLEN]; + + if (!am_server && passwd[0] != 0) { + strlcpy(secbuf, passwd, sizeof(secbuf)); + } else { + return 0; + } + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + error("Secret for %s on %s is too long", client, server); + len = MAXSECRETLEN; + } + BCOPY(secbuf, secret, len); + BZERO(secbuf, sizeof(secbuf)); *secret_len = len; -#endif + return 1; } /* * set_allowed_addrs() - set the list of allowed addresses. + * Also looks for `--' indicating options to apply for this peer + * and leaves the following words in extra_options. */ static void -set_allowed_addrs(unit, addrs) +set_allowed_addrs(unit, addrs, opts) int unit; struct wordlist *addrs; + struct wordlist *opts; { + int n; + struct wordlist *ap, **pap; + struct permitted_ip *ip; + char *ptr_word, *ptr_mask; + struct hostent *hp; + struct netent *np; + u_int32_t a, mask, ah, offset; + struct ipcp_options *wo = &ipcp_wantoptions[unit]; + u_int32_t suggested_ip = 0; + + if (addresses[unit] != NULL) + free(addresses[unit]); + addresses[unit] = NULL; + if (extra_options != NULL) + free_wordlist(extra_options); + extra_options = opts; + + /* + * Count the number of IP addresses given. + */ + for (n = 0, pap = &addrs; (ap = *pap) != NULL; pap = &ap->next) + ++n; + if (n == 0) + return; + ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); + if (ip == 0) + return; + + n = 0; + for (ap = addrs; ap != NULL; ap = ap->next) { + /* "-" means no addresses authorized, "*" means any address allowed */ + ptr_word = ap->word; + if (strcmp(ptr_word, "-") == 0) + break; + if (strcmp(ptr_word, "*") == 0) { + ip[n].permit = 1; + ip[n].base = ip[n].mask = 0; + ++n; + break; + } + + ip[n].permit = 1; + if (*ptr_word == '!') { + ip[n].permit = 0; + ++ptr_word; + } + + mask = ~ (u_int32_t) 0; + offset = 0; + ptr_mask = strchr (ptr_word, '/'); + if (ptr_mask != NULL) { + int bit_count; + char *endp; + + bit_count = (int) strtol (ptr_mask+1, &endp, 10); + if (bit_count <= 0 || bit_count > 32) { + warn("invalid address length %v in auth. address list", + ptr_mask+1); + continue; + } + bit_count = 32 - bit_count; /* # bits in host part */ + if (*endp == '+') { + offset = pppifunit + 1; + ++endp; + } + if (*endp != 0) { + warn("invalid address length syntax: %v", ptr_mask+1); + continue; + } + *ptr_mask = '\0'; + mask <<= 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) { + warn("unknown host %s in auth. address list", ap->word); + continue; + } + if (offset != 0) { + if (offset >= ~mask) { + warn("interface unit %d too large for subnet %v", + pppifunit, ptr_word); + continue; + } + a = htonl((ntohl(a) & mask) + offset); + mask = ~(u_int32_t)0; + } + ip[n].mask = htonl(mask); + ip[n].base = a & ip[n].mask; + ++n; + if (~mask == 0 && suggested_ip == 0) + suggested_ip = a; + } + + ip[n].permit = 0; /* make the last entry forbid all addresses */ + ip[n].base = 0; /* to terminate the list */ + ip[n].mask = 0; + + addresses[unit] = ip; + + /* + * If the address given for the peer isn't authorized, or if + * the user hasn't given one, AND there is an authorized address + * which is a single host, then use that if we find one. + */ + if (suggested_ip != 0 + && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) + wo->hisaddr = suggested_ip; } /* @@ -741,30 +1011,30 @@ 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; -{ -#if 0 - u_int32_t a, mask, ah; - int accept; - char *ptr_word, *ptr_mask; - struct hostent *hp; - struct netent *np; -#endif + int ok; /* don't allow loopback or multicast address */ if (bad_ip_adrs(addr)) return 0; - if (addrs == NULL) - return !auth_required; /* no addresses authorized */ + if (addresses[unit] != NULL) { + ok = ip_addr_check(addr, addresses[unit]); + if (ok >= 0) + return ok; + } + if (auth_required) + return 0; /* no addresses authorized */ + return allow_any_ip || !have_route_to(addr); +} - return 1; +static int +ip_addr_check(addr, addrs) + u_int32_t addr; + struct permitted_ip *addrs; +{ + for (; ; ++addrs) + if ((addr & addrs->mask) == addrs->base) + return addrs->permit; } /* @@ -781,41 +1051,6 @@ bad_ip_adrs(addr) || 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; -{ - -} - - -/* - * 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; -{ - - return -1; -} - /* * free_wordlist - release memory allocated for a wordlist. */ @@ -837,7 +1072,21 @@ free_wordlist(wp) * interface-name peer-name real-user tty speed */ static void -auth_script(script) - char *script; +auth_script(s) + enum script_state s; { + switch (s) { + case s_up: + auth_script_state = s_up; + if ( auth_linkup_hook ) { + (*auth_linkup_hook)(); + } + break; + case s_down: + auth_script_state = s_down; + if ( auth_linkdown_hook ) { + (*auth_linkdown_hook)(); + } + break; + } } diff --git a/c/src/libnetworking/pppd/cbcp.c b/c/src/libnetworking/pppd/cbcp.c deleted file mode 100644 index 147e56a07b..0000000000 --- a/c/src/libnetworking/pppd/cbcp.c +++ /dev/null @@ -1,431 +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[] = "$Id$"; */ -#endif - -#include -#include -#include -#include -#include - -#include "pppd.h" -#include "cbcp.h" -#include "fsm.h" -#include "lcp.h" -#include "ipcp.h" - -/* - * Protocol entry points. - */ -static void cbcp_init __P((int unit)); -static void cbcp_open __P((int unit)); -static void cbcp_lowerup __P((int unit)); -static void cbcp_input __P((int unit, u_char *pkt, int len)); -static void cbcp_protrej __P((int unit)); -static int cbcp_printpkt __P((u_char *pkt, int len, - void (*printer) __P((void *, char *, ...)), - void *arg)); - -struct protent cbcp_protent = { - PPP_CBCP, - cbcp_init, - cbcp_input, - cbcp_protrej, - cbcp_lowerup, - NULL, - cbcp_open, - NULL, - cbcp_printpkt, - NULL, - 0, - "CBCP", - NULL, - NULL, - NULL -}; - -cbcp_state cbcp[NUM_PPP]; - -/* internal prototypes */ - -static void cbcp_recvreq __P((cbcp_state *us, char *pckt, int len)); -static void cbcp_resp __P((cbcp_state *us)); -static void cbcp_up __P((cbcp_state *us)); -static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len)); -static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len)); - -/* init state */ -static void -cbcp_init(iface) - int iface; -{ - cbcp_state *us; - - us = &cbcp[iface]; - memset(us, 0, sizeof(cbcp_state)); - us->us_unit = iface; - us->us_type |= (1 << CB_CONF_NO); -} - -/* lower layer is up */ -static void -cbcp_lowerup(iface) - int iface; -{ - cbcp_state *us = &cbcp[iface]; - - - 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(unit) - int unit; -{ - syslog(LOG_DEBUG, "cbcp_open"); -} - -/* process an incomming packet */ -static void -cbcp_input(unit, inpacket, pktlen) - int unit; - u_char *inpacket; - int pktlen; -{ - u_char *inp; - u_char code, id; - u_short len; - - cbcp_state *us = &cbcp[unit]; - - inp = inpacket; - - if (pktlen < CBCP_MINLEN) { - syslog(LOG_ERR, "CBCP packet is too small"); - return; - } - - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - -#if 0 - if (len > pktlen) { - syslog(LOG_ERR, "CBCP packet: invalid length"); - return; - } -#endif - - 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(p, plen, printer, arg) - u_char *p; - int plen; - void (*printer) __P((void *, char *, ...)); - void *arg; -{ - int code, opt, id, len, olen, delay; - u_char *pstart; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *)) - printer(arg, " %s", cbcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - - switch (code) { - case CBCP_REQ: - case CBCP_RESP: - case CBCP_ACK: - while(len >= 2) { - GETCHAR(opt, p); - GETCHAR(olen, p); - - if (olen < 2 || olen > len) { - break; - } - - printer(arg, " <"); - len -= olen; - - if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *)) - printer(arg, " %s", cbcp_optionnames[opt-1]); - else - printer(arg, " option=0x%x", opt); - - if (olen > 2) { - GETCHAR(delay, p); - printer(arg, " delay = %d", delay); - } - - if (olen > 3) { - int addrt; - char str[256]; - - GETCHAR(addrt, p); - memcpy(str, p, olen - 4); - str[olen - 4] = 0; - printer(arg, " number = %s", str); - } - printer(arg, ">"); - break; - } - - default: - break; - } - - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} - -/* received CBCP request */ -static void -cbcp_recvreq(us, pckt, pcktlen) - cbcp_state *us; - char *pckt; - int pcktlen; -{ - u_char type, opt_len, delay, addr_type; - char address[256]; - int len = pcktlen; - - address[0] = 0; - - while (len) { - syslog(LOG_DEBUG, "length: %d", len); - - GETCHAR(type, pckt); - GETCHAR(opt_len, pckt); - - 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; - } - len -= opt_len; - } - - cbcp_resp(us); -} - -static void -cbcp_resp(us) - cbcp_state *us; -{ - u_char cb_type; - u_char buf[256]; - u_char *bufp = buf; - int len = 0; - - 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 + 1; - PUTCHAR(len , bufp); - PUTCHAR(5, bufp); /* delay */ - PUTCHAR(0, bufp); - 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 = 3; - PUTCHAR(len , bufp); - PUTCHAR(0, bufp); - cbcp_send(us, CBCP_RESP, buf, len); - (*ipcp_protent.open)(us->us_unit); - return; - } -} - -static void -cbcp_send(us, code, buf, len) - 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(us, pckt, len) - cbcp_state *us; - char *pckt; - int len; -{ - u_char type, delay, addr_type; - int opt_len; - char address[256]; - - if (len) { - GETCHAR(type, pckt); - GETCHAR(opt_len, pckt); - - 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(us) - cbcp_state *us; -{ - persist = 0; - lcp_close(0, "Call me back, please"); -} diff --git a/c/src/libnetworking/pppd/cbcp.h b/c/src/libnetworking/pppd/cbcp.h deleted file mode 100644 index c2ab3f6899..0000000000 --- a/c/src/libnetworking/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/c/src/libnetworking/pppd/ccp.c b/c/src/libnetworking/pppd/ccp.c index 1467c6e411..094a96d8f5 100644 --- a/c/src/libnetworking/pppd/ccp.c +++ b/c/src/libnetworking/pppd/ccp.c @@ -25,20 +25,60 @@ * OR MODIFICATIONS. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" +#include #include -#include -#include -#include #include "pppd.h" #include "fsm.h" #include "ccp.h" #include +static const char rcsid[] = RCSID; + +/* + * Command-line options. + */ +static int setbsdcomp __P((char **)); +static int setdeflate __P((char **)); + +static option_t ccp_option_list[] = { + { "noccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation" }, + { "-ccp", o_bool, &ccp_protent.enabled_flag, + "Disable CCP negotiation" }, + { "bsdcomp", o_special, setbsdcomp, + "Request BSD-Compress packet compression" }, + { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_A2COPY, + &ccp_allowoptions[0].bsd_compress }, + { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, + "don't allow BSD-Compress", OPT_A2COPY, + &ccp_allowoptions[0].bsd_compress }, + { "deflate", 1, setdeflate, + "request Deflate compression" }, + { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_A2COPY, + &ccp_allowoptions[0].deflate }, + { "-deflate", o_bool, &ccp_wantoptions[0].deflate, + "don't allow Deflate compression", OPT_A2COPY, + &ccp_allowoptions[0].deflate }, + { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, + "don't use draft deflate #", OPT_A2COPY, + &ccp_allowoptions[0].deflate_draft }, + { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 }, + { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_A2COPY, + &ccp_allowoptions[0].predictor_1 }, + { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, + "don't allow Predictor-1", OPT_A2COPY, + &ccp_allowoptions[0].predictor_1 }, + + { NULL } +}; + /* * Protocol entry points from main code. */ @@ -67,6 +107,8 @@ struct protent ccp_protent = { ccp_datainput, 1, "CCP", + "Compressed", + ccp_option_list, NULL, NULL, NULL @@ -129,6 +171,83 @@ static int ccp_localstate[NUM_PPP]; static int all_rejected[NUM_PPP]; /* we rejected all peer's options */ +/* + * Option parsing. + */ +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 +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; + return 1; +} + + /* * ccp_init - initialize CCP. */ @@ -237,8 +356,8 @@ ccp_input(unit, p, len) */ 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 (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) + notice("Compression disabled by peer."); /* * If we get a terminate-ack and we're not asking for compression, @@ -589,12 +708,9 @@ ccp_nakci(f, p, len) /* * Predictor-1 and 2 have no options, so they can't be Naked. * - * XXX What should we do with any remaining options? + * There may be remaining options but we ignore them. */ - if (len != 0) - return 0; - if (f->state != OPENED) *go = try; return 1; @@ -872,27 +988,28 @@ method_name(opt, opt2) 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); + slprintf(result, sizeof(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); + slprintf(result, sizeof(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); + slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", + opt->bsd_bits, opt2->bsd_bits); else - sprintf(result, "BSD-Compress (%d)", opt->bsd_bits); + slprintf(result, sizeof(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); + slprintf(result, sizeof(result), "Method %d", opt->method); } return result; } @@ -912,23 +1029,16 @@ ccp_up(f) if (ANY_COMPRESS(*go)) { if (ANY_COMPRESS(*ho)) { if (go->method == ho->method) { - syslog(LOG_NOTICE, "%s compression enabled", - method_name(go, ho)) -; + 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)) -; + strlcpy(method1, method_name(go, NULL), sizeof(method1)); + notice("%s / %s compression enabled", + method1, method_name(ho, NULL)); } } else - syslog(LOG_NOTICE, "%s receive compression enabled", - method_name(go, NULL)) -; + 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)) -; + notice("%s transmit compression enabled", method_name(ho, NULL)); } /* @@ -1031,26 +1141,26 @@ ccp_printpkt(p, plen, printer, arg) } break; } -/* while (p < optend) + while (p < optend) printer(arg, " %.2x", *p++); printer(arg, ">"); -*/ } + } break; case TERMACK: case TERMREQ: -/* if (len > 0 && *p >= ' ' && *p < 0x7f) { + if (len > 0 && *p >= ' ' && *p < 0x7f) { print_string(p, len, printer, arg); p += len; len = 0; } -*/ break; + break; } /* dump out the rest of the packet in hex */ -/* while (--len >= 0) + while (--len >= 0) printer(arg, " %.2x", *p++); -*/ + return p - p0; } @@ -1080,7 +1190,7 @@ ccp_datainput(unit, pkt, len) /* * Disable compression by taking CCP down. */ - syslog(LOG_ERR, "Lost compression sync: disabling compression"); + error("Lost compression sync: disabling compression"); ccp_close(unit, "Lost compression sync"); } else { /* diff --git a/c/src/libnetworking/pppd/ccp.h b/c/src/libnetworking/pppd/ccp.h index af421d48c3..609d858c5e 100644 --- a/c/src/libnetworking/pppd/ccp.h +++ b/c/src/libnetworking/pppd/ccp.h @@ -28,12 +28,12 @@ */ typedef struct ccp_options { - u_int bsd_compress: 1; /* do BSD Compress? */ - u_int deflate: 1; /* do Deflate? */ - 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? */ + bool bsd_compress; /* do BSD Compress? */ + bool deflate; /* do Deflate? */ + bool predictor_1; /* do Predictor-1? */ + bool predictor_2; /* do Predictor-2? */ + bool deflate_correct; /* use correct code for deflate? */ + bool deflate_draft; /* use draft RFC code for deflate? */ u_short bsd_bits; /* # bits/code for BSD Compress */ u_short deflate_size; /* lg(window size) for Deflate */ short method; /* code for chosen compression method */ diff --git a/c/src/libnetworking/pppd/chap.c b/c/src/libnetworking/pppd/chap.c index de80fdf666..15d0210369 100644 --- a/c/src/libnetworking/pppd/chap.c +++ b/c/src/libnetworking/pppd/chap.c @@ -33,9 +33,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" /* * TODO: @@ -45,7 +43,6 @@ #include #include #include -#include #include "pppd.h" #include "chap.h" @@ -54,6 +51,25 @@ #include "chap_ms.h" #endif +static const char rcsid[] = RCSID; + +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap[0].timeouttime, + "Set timeout for CHAP" }, + { "chap-max-challenge", o_int, &chap[0].max_transmits, + "Set max #xmits for challenge" }, + { "chap-interval", o_int, &chap[0].chal_interval, + "Set interval for rechallenge" }, +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif + { NULL } +}; + /* * Protocol entry points. */ @@ -79,6 +95,8 @@ struct protent chap_protent = { 1, "CHAP", NULL, + chap_option_list, + NULL, NULL, NULL }; @@ -96,13 +114,8 @@ static void ChapSendStatus __P((chap_state *, int)); static void ChapSendChallenge __P((chap_state *)); static void ChapSendResponse __P((chap_state *)); static void ChapGenChallenge __P((chap_state *)); -/* #include */ extern double drand48 __P((void)); -/*{ - return (((double)rand())/RAND_MAX); -} -*/ extern void srand48 __P((long)); /* @@ -199,7 +212,7 @@ ChapChallengeTimeout(arg) if (cstate->chal_transmits >= cstate->max_transmits) { /* give up on peer */ - syslog(LOG_ERR, "Peer failed to respond to CHAP challenge"); + error("Peer failed to respond to CHAP challenge"); cstate->serverstate = CHAPSS_BADAUTH; auth_peer_fail(cstate->unit, PPP_CHAP); return; @@ -336,18 +349,18 @@ ChapInput(unit, inpacket, packet_len) */ inp = inpacket; if (packet_len < CHAP_HEADERLEN) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.")); + CHAPDEBUG(("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.")); + CHAPDEBUG(("ChapInput: rcvd illegal length.")); return; } if (len > packet_len) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.")); + CHAPDEBUG(("ChapInput: rcvd short packet.")); return; } len -= CHAP_HEADERLEN; @@ -373,7 +386,7 @@ ChapInput(unit, inpacket, packet_len) break; default: /* Need code reject? */ - syslog(LOG_WARNING, "Unknown CHAP code (%d) received.", code); + warn("Unknown CHAP code (%d) received.", code); break; } } @@ -397,23 +410,21 @@ ChapReceiveChallenge(cstate, inp, id, len) 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)); + CHAPDEBUG(("ChapReceiveChallenge: in state %d", cstate->clientstate)); return; } if (len < 2) { - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.")); + CHAPDEBUG(("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.")); + CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet.")); return; } rchallenge = inp; @@ -424,14 +435,10 @@ ChapReceiveChallenge(cstate, inp, id, len) 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", + if (explicit_remote || (remote_name[0] != 0 && rhostname[0] == 0)) { + strlcpy(rhostname, remote_name, sizeof(rhostname)); + CHAPDEBUG(("ChapReceiveChallenge: using '%q' as remote name", rhostname)); } @@ -439,8 +446,7 @@ ChapReceiveChallenge(cstate, inp, id, len) 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); + warn("No CHAP secret found for authenticating us to %q", rhostname); } /* cancel response send timeout if necessary */ @@ -470,7 +476,7 @@ ChapReceiveChallenge(cstate, inp, id, len) #endif default: - CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type)); + CHAPDEBUG(("unknown digest type %d", cstate->resp_type)); return; } @@ -497,12 +503,9 @@ ChapReceiveResponse(cstate, inp, id, len) 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)); + CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate)); return; } @@ -524,7 +527,7 @@ ChapReceiveResponse(cstate, inp, id, len) } if (len < 2) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.")); + CHAPDEBUG(("ChapReceiveResponse: rcvd short packet.")); return; } GETCHAR(remmd_len, inp); /* get length of MD */ @@ -533,7 +536,7 @@ ChapReceiveResponse(cstate, inp, id, len) len -= sizeof (u_char) + remmd_len; if (len < 0) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.")); + CHAPDEBUG(("ChapReceiveResponse: rcvd short packet.")); return; } @@ -544,18 +547,14 @@ ChapReceiveResponse(cstate, inp, id, len) 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); + if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname), + cstate->chal_name, secret, &secret_len, 1)) { + warn("No CHAP secret found for authenticating %q", rhostname); } else { /* generate MD based on negotiated type */ @@ -576,7 +575,7 @@ ChapReceiveResponse(cstate, inp, id, len) break; default: - CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->chal_type)); + CHAPDEBUG(("unknown digest type %d", cstate->chal_type)); } } @@ -591,12 +590,10 @@ ChapReceiveResponse(cstate, inp, id, len) } if (cstate->chal_interval != 0) TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); - syslog(LOG_NOTICE, "CHAP peer authentication succeeded for %s", - rhostname); + notice("CHAP peer authentication succeeded for %q", rhostname); } else { - syslog(LOG_ERR, "CHAP peer authentication failed for remote host %s", - rhostname); + error("CHAP peer authentication failed for remote host %q", rhostname); cstate->serverstate = CHAPSS_BADAUTH; auth_peer_fail(cstate->unit, PPP_CHAP); } @@ -609,20 +606,17 @@ static void ChapReceiveSuccess(cstate, inp, id, len) chap_state *cstate; u_char *inp; - int id; /* was u_char id */ + 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)); + CHAPDEBUG(("ChapReceiveSuccess: in state %d\n", cstate->clientstate)); return; } @@ -647,15 +641,12 @@ static void ChapReceiveFailure(cstate, inp, id, len) chap_state *cstate; u_char *inp; - int id; /* was u_char id; */ + 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)); + CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate)); return; } @@ -667,7 +658,7 @@ ChapReceiveFailure(cstate, inp, id, len) if (len > 0) PRINTMSG(inp, len); - syslog(LOG_ERR, "CHAP authentication failed"); + error("CHAP authentication failed"); auth_withpeer_fail(cstate->unit, PPP_CHAP); } @@ -702,8 +693,6 @@ ChapSendChallenge(cstate) 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; } @@ -722,9 +711,9 @@ ChapSendStatus(cstate, code) char msg[256]; if (code == CHAP_SUCCESS) - sprintf(msg, "Welcome to %s.", hostname); + slprintf(msg, sizeof(msg), "Welcome to %s.", hostname); else - sprintf(msg, "I don't like you. Go 'way."); + slprintf(msg, sizeof(msg), "I don't like you. Go 'way."); msglen = strlen(msg); outlen = CHAP_HEADERLEN + msglen; @@ -737,9 +726,6 @@ ChapSendStatus(cstate, code) 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)); } /* @@ -755,7 +741,7 @@ ChapGenChallenge(cstate) { int chal_len; u_char *ptr = cstate->challenge; - unsigned int i; + int i; /* pick a random challenge length between MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH */ @@ -767,7 +753,7 @@ ChapGenChallenge(cstate) cstate->chal_transmits = 0; /* generate a random string */ - for (i = 0; i < chal_len; i++ ) + for (i = 0; i < chal_len; i++) *ptr++ = (char) (drand48() * 0xff); } @@ -825,6 +811,7 @@ ChapPrintPkt(p, plen, printer, arg) int code, id, len; int clen, nlen; u_char x; + if (plen < CHAP_HEADERLEN) return 0; GETCHAR(code, p); @@ -868,5 +855,6 @@ ChapPrintPkt(p, plen, printer, arg) printer(arg, " %.2x", x); } } + return len + CHAP_HEADERLEN; } diff --git a/c/src/libnetworking/pppd/chap.h b/c/src/libnetworking/pppd/chap.h index 6e2cc45e89..945d051d06 100644 --- a/c/src/libnetworking/pppd/chap.h +++ b/c/src/libnetworking/pppd/chap.h @@ -55,8 +55,8 @@ /* * Challenge lengths (for challenges we send) and other limits. */ -#define MIN_CHALLENGE_LENGTH 32 -#define MAX_CHALLENGE_LENGTH 64 +#define MIN_CHALLENGE_LENGTH 16 +#define MAX_CHALLENGE_LENGTH 24 #define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ /* diff --git a/c/src/libnetworking/pppd/chap_ms.c b/c/src/libnetworking/pppd/chap_ms.c index 2de98dbb66..81a57bb5aa 100644 --- a/c/src/libnetworking/pppd/chap_ms.c +++ b/c/src/libnetworking/pppd/chap_ms.c @@ -31,18 +31,16 @@ * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" #ifdef CHAPMS #include +#include #include #include #include #include -#include #include #ifdef HAVE_CRYPT_H #include @@ -57,6 +55,8 @@ #include #endif +static const char rcsid[] = RCSID; + typedef struct { u_char LANManResp[24]; u_char NTResp[24]; @@ -80,6 +80,11 @@ static void Expand __P((u_char *, u_char *)); static void Collapse __P((u_char *, u_char *)); #endif +#ifdef MSLANMAN +bool ms_lanman = 0; /* Use LanMan password instead of NT */ + /* Has meaning only with MS-CHAP challenges */ +#endif + static void ChallengeResponse(challenge, pwHash, response) u_char *challenge; /* IN 8 octets */ @@ -92,7 +97,8 @@ ChallengeResponse(challenge, pwHash, response) BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE); #if 0 - log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); + dbglog("ChallengeResponse - ZPasswordHash %.*B", + sizeof(ZPasswordHash), ZPasswordHash); #endif DesEncrypt(challenge, ZPasswordHash + 0, response + 0); @@ -100,7 +106,7 @@ ChallengeResponse(challenge, pwHash, response) DesEncrypt(challenge, ZPasswordHash + 14, response + 16); #if 0 - log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); + dbglog("ChallengeResponse - response %.24B", response); #endif } @@ -122,8 +128,7 @@ DesEncrypt(clear, key, cipher) 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])); + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear)); #endif Expand(clear, des_input); @@ -131,8 +136,7 @@ DesEncrypt(clear, key, cipher) 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])); + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher)); #endif } @@ -152,15 +156,13 @@ DesEncrypt(clear, key, cipher) 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])); + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear)); #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])); + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher)); #endif } @@ -239,10 +241,8 @@ static void MakeKey(key, 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])); + CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key)); + CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key)); #endif } @@ -255,6 +255,12 @@ ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response) MS_ChapResponse *response; { int i; +#ifdef __NetBSD__ + /* NetBSD uses the libc md4 routines which take bytes instead of bits */ + int mdlen = secret_len * 2; +#else + int mdlen = secret_len * 2 * 8; +#endif MD4_CTX md4Context; u_char hash[MD4_SIGNATURE_SIZE]; u_char unicodePassword[MAX_NT_PASSWORD * 2]; @@ -266,7 +272,7 @@ ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response) unicodePassword[i * 2] = (u_char)secret[i]; MD4Init(&md4Context); - MD4Update(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ + MD4Update(&md4Context, unicodePassword, mdlen); MD4Final(hash, &md4Context); /* Tell MD4 we're done */ @@ -307,9 +313,6 @@ ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len) 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)); diff --git a/c/src/libnetworking/pppd/chat.c b/c/src/libnetworking/pppd/chat.c index eca2066e93..31273714b4 100644 --- a/c/src/libnetworking/pppd/chat.c +++ b/c/src/libnetworking/pppd/chat.c @@ -156,7 +156,6 @@ int Verbose = 0; int quiet = 0; int report = 0; int exit_code = 0; -static int speed=0; char *report_file = (char *) 0; char *chat_file = (char *) 0; char *phone_num = (char *) 0; @@ -167,8 +166,8 @@ int have_tty_parameters = 0; #ifdef TERMIOS #define term_parms struct termios -#define get_term_param(param) tcgetattr(modem_fd, param) -#define set_term_param(param) tcsetattr(modem_fd, TCSANOW, param) +#define get_term_param(param) tcgetattr(ttyfd, param) +#define set_term_param(param) tcsetattr(ttyfd, TCSANOW, param) struct termios saved_tty_parameters; #endif @@ -260,52 +259,35 @@ char *getnextcommand(char **string) } -extern int modem_fd; -int - chatmain(argv) - char *argv; +extern int ttyfd; +int chatmain(argv) +char *argv; { - char *arg; - int i; - char *t; - exit_code=0; - speed=0; -/* - * Default the report file to the stderr location - */ -/* if (report_fp == NULL) - report_fp = stderr; -*/ - init(); - while ( (arg = getnextcommand(&argv)) != NULL) { - chat_expect(arg); - if (exit_code>0) break; - t=temp2; - - while(*t) - { - if (strncmp("CARRIER",t,7)==0) - {/* parse speed information */ - i=0; - while(!isdigit(t[i])) - i++; - t=&t[i]; - i=0; - while(isdigit(t[i])) - i++; - t[i]=0; - sscanf(t,"%d",&speed); - break; - } - t++; - } - if ((arg = getnextcommand(&argv)) != NULL) - chat_send(arg); - if (exit_code>0) break; - } + char *arg; + + /* initialize exit code */ + exit_code = 0; + +printf("chat_main: %s\n", argv); + + /* get first expect string */ + arg = getnextcommand(&argv); + while ( arg != NULL ) { + /* process the expect string */ + chat_expect(arg); + + /* get the next send string */ + arg = getnextcommand(&argv); + if ( arg != NULL ) { + /* process the send string */ + chat_send(arg); + + /* get the next expect string */ + arg = getnextcommand(&argv); + } + } - if (exit_code) return exit_code; - return -speed; + return 0; } @@ -317,7 +299,6 @@ int void init() { set_tty_parameters(); - speed=0; } void set_tty_parameters() @@ -657,7 +638,7 @@ register char *s; if (say_next) { say_next = 0; s = clean(s,0); - write(modem_fd, s, strlen(s)); + write(ttyfd, s, strlen(s)); free(s); return; } @@ -682,63 +663,6 @@ register char *s; return; } - -/* if (report_next) { - char *s1; - - report_next = 0; - if (n_reports >= MAX_REPORTS) - { - exit_code=2; - return; - } - - s1 = clean(s, 0); - - if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1) - { - exit_code=1; - return; - } - - report_string[n_reports++] = s1; - - return; - } -*/ -/* if (clear_report_next) { - char *s1; - int i; - int old_max; - int pack = 0; - - clear_report_next = 0; - - s1 = clean(s, 0); - - if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1) - { - exit_code=1; - return; - } - - old_max = n_reports; - for (i=0; i < n_reports; i++) { - if ( strcmp(s1,report_string[i]) == 0 ) { - free(report_string[i]); - report_string[i] = NULL; - pack++; - n_reports--; - } - } - free(s1); - if (pack) - pack_array(report_string,old_max); - - return; - } -*/ - if (timeout_next) { timeout=atoi(s); timeout_next = 0; @@ -770,7 +694,7 @@ int get_char() while(tries) { - status = read(modem_fd, &c, 1); + status = read(ttyfd, &c, 1); switch (status) { case 1: return ((int)c & 0x7F); @@ -789,7 +713,7 @@ int c; /* inter-character typing delay (?) */ - status = write(modem_fd, &ch, 1); + status = write(ttyfd, &ch, 1); switch (status) { case 1: @@ -814,8 +738,6 @@ int c; int put_string (s) register char *s; { - - quiet = 0; s = clean(s, 1); while (*s) { @@ -898,10 +820,10 @@ register char *string; char *logged = temp2; struct termios tios; - tcgetattr(modem_fd, &tios); + tcgetattr(ttyfd, &tios); tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS; - tcsetattr(modem_fd, TCSANOW, &tios); + tcsetattr(ttyfd, TCSANOW, &tios); string = clean(string, 0); len = strlen(string); diff --git a/c/src/libnetworking/pppd/demand.c b/c/src/libnetworking/pppd/demand.c index a1910f258f..1f2e9932d4 100644 --- a/c/src/libnetworking/pppd/demand.c +++ b/c/src/libnetworking/pppd/demand.c @@ -17,16 +17,13 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$"; #include #include #include #include #include -#include #include #include #include @@ -46,6 +43,8 @@ #include "ipcp.h" #include "lcp.h" +static const char rcsid[] = RCSID; + char *frame; int framelen; int framemax; @@ -262,7 +261,7 @@ loop_frame(frame, len) { struct packet *pkt; - /* log_packet(frame, len, "from loop: ", LOG_DEBUG); */ + /* dbglog("from loop: %P", frame, len); */ if (len < PPP_HDRLEN) return 0; if ((PPP_PROTOCOL(frame) & 0x8000) != 0) diff --git a/c/src/libnetworking/pppd/example/Makefile b/c/src/libnetworking/pppd/example/Makefile new file mode 100644 index 0000000000..69cc8aab50 --- /dev/null +++ b/c/src/libnetworking/pppd/example/Makefile @@ -0,0 +1,45 @@ +# +# Makefile +# + +# +# RTEMS_MAKEFILE_PATH is typically set in an environment variable +# + +EXEC=ppptest.exe +PGM=${ARCH}/$(EXEC) + +# optional managers required +MANAGERS=io event semaphore + +# C source names +CSRCS = init.c pppdapp.c + +COBJS_ = $(CSRCS:.c=.o) +COBJS = $(COBJS_:%=${ARCH}/%) + +# C++ source names +CXXSRCS = +CXXOBJS_ = $(CXXSRCS:.cc=.o) +CXXOBJS = $(CXXOBJS_:%=${ARCH}/%) + +# AS source names +ASSRCS = +ASOBJS_ = $(ASSRCS:.s=.o) +ASOBJS = $(ASOBJS_:%=${ARCH}/%) + +# Libraries +LIBS = -lrtemsall -lc + +include $(RTEMS_MAKEFILE_PATH)/Makefile.inc + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/leaf.cfg + +OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS) + +all: ${ARCH} $(PGM) + +$(PGM): $(OBJS) + $(make-exe) + diff --git a/c/src/libnetworking/pppd/example/README b/c/src/libnetworking/pppd/example/README new file mode 100644 index 0000000000..786d03844b --- /dev/null +++ b/c/src/libnetworking/pppd/example/README @@ -0,0 +1,6 @@ +# +# $Id$ +# + +This is an example user application using pppd. It is built using +the RTEMS application Makefiles. diff --git a/c/src/libnetworking/pppd/example/init.c b/c/src/libnetworking/pppd/example/init.c new file mode 100644 index 0000000000..f35d195bf2 --- /dev/null +++ b/c/src/libnetworking/pppd/example/init.c @@ -0,0 +1,24 @@ + +#include +#include +#include +#include +#include + +#define CONFIGURE_INIT +#include "system.h" +#include "netconfig.h" + + +extern int pppdapp_initialize(void); + + +rtems_task Init(rtems_task_argument argument) +{ + /* initialize network */ + rtems_bsdnet_initialize_network(); + rtems_pppd_initialize(); + pppdapp_initialize(); + + rtems_task_delete(RTEMS_SELF); +} diff --git a/c/src/libnetworking/pppd/example/netconfig.h b/c/src/libnetworking/pppd/example/netconfig.h new file mode 100644 index 0000000000..6a95cce189 --- /dev/null +++ b/c/src/libnetworking/pppd/example/netconfig.h @@ -0,0 +1,37 @@ + +#ifndef NETCONFIG_H_ +#define NETCONFIG_H_ + +#include + +/* external function prototypes */ +extern int rtems_ppp_driver_attach(struct rtems_bsdnet_ifconfig *config, + int attaching); + +/* Default network interface */ +static struct rtems_bsdnet_ifconfig netdriver_config = { + "ppp0", /* name */ + rtems_ppp_driver_attach, /* attach function */ + NULL, /* No more interfaces */ + "192.168.2.123", /* IP address */ + "255.255.255.0", /* IP net mask */ + NULL, /* Driver supplies hardware address */ + 0 /* Use default driver parameters */ +}; + +/* Network configuration */ +struct rtems_bsdnet_config rtems_bsdnet_config = { + &netdriver_config, + NULL, + 0, /* Default network task priority */ + 0, /* Default mbuf capacity */ + 0, /* Default mbuf cluster capacity */ + "rtems", /* Host name */ + "xxxyyy.com", /* Domain name */ + 0, /* Gateway */ + 0, /* Log host */ + { 0 }, /* Name server(s) */ + { 0 }, /* NTP server(s) */ +}; + +#endif diff --git a/c/src/libnetworking/pppd/example/ppp.conf b/c/src/libnetworking/pppd/example/ppp.conf new file mode 100644 index 0000000000..094b1946a8 --- /dev/null +++ b/c/src/libnetworking/pppd/example/ppp.conf @@ -0,0 +1,27 @@ + +# +# Example configuration file for setting up a ppp server +# using a null-modem serial cable: +# +# Tested using ppp on OpenBSD 2.9 +# - just follow instructions in man page for accepting +# ppp connections over the serial port +# - if pap and/or chap is enabled, you must have a ppp.secret +# file which will be used for user authentication +# - found useful to turn on syslog for ppp +# + +default: + set log Phase Chat LQM LCP IPCP CCP command + set device /dev/cua00 + set speed 57600 + set ctsrts on + set dial "" + +openbsd-server: + set timeout 0 + set ifaddr 192.168.2.100 192.168.2.123 + enable dns + allow users + enable chap + enable pap diff --git a/c/src/libnetworking/pppd/example/pppdapp.c b/c/src/libnetworking/pppd/example/pppdapp.c new file mode 100644 index 0000000000..59e5029088 --- /dev/null +++ b/c/src/libnetworking/pppd/example/pppdapp.c @@ -0,0 +1,146 @@ + +#include +#include +#include "system.h" + + +/* define global variables */ +static unsigned int pppdapp_linkcount = 0; +static rtems_id pppdapp_taskid; + + +static void pppdapp_linkup_hook(void) +{ + pppdapp_linkcount++; + printf("PPP LINK UP [%d]\n", pppdapp_linkcount); +} + +static void pppdapp_linkdown_hook(void) +{ + printf("PPP LINK DOWN [%d]\n", pppdapp_linkcount); +} + +static void pppdapp_ipup_hook(void) +{ + /* send ipup signal to pppdapp task */ + rtems_event_send(pppdapp_taskid, RTEMS_EVENT_10); +} + +static void pppdapp_ipdown_hook(void) +{ + /* send ip down signal to pppdapp task */ + rtems_event_send(pppdapp_taskid, RTEMS_EVENT_11); +} + +static void pppdapp_setup(void) +{ + const char *pUser = "oscar"; + const char *pPassword = "goldman"; + +#undef USE_MODEM +#ifdef USE_MODEM + const char *pTelephone = "5551234"; + const char *pInitScript = "TIMEOUT@5@@AT@@OK@"; + const char *pConnectScript = "TIMEOUT@90@@ATDT%s@CONNECT@@name:@%s@word:@%s@"; + const char *pDisconnectScript = "TIMEOUT@5@@ATH0@@OK@"; + char pConnect[128]; + + /* set the connect string */ + sprintf(pConnect, pConnectScript, pTelephone, pUser, pPassword); + + /* set pppd options for modem */ + rtems_pppd_set_option("/dev/ttyS2", NULL); + rtems_pppd_set_option("57600", NULL); + rtems_pppd_set_option("crtscts", NULL); + rtems_pppd_set_option("modem", NULL); + rtems_pppd_set_option("noauth", NULL); + rtems_pppd_set_option("debug", NULL); + rtems_pppd_set_option("init", pInitScript); + rtems_pppd_set_option("connect", pConnect); + rtems_pppd_set_option("disconnect", pDisconnectScript); +#else + /* set pppd options for null modem direct link serial cable */ + rtems_pppd_set_option("/dev/ttyS1", NULL); + rtems_pppd_set_option("57600", NULL); + rtems_pppd_set_option("crtscts", NULL); + rtems_pppd_set_option("local", NULL); + rtems_pppd_set_option("noauth", NULL); + rtems_pppd_set_option("debug", NULL); + rtems_pppd_set_option("user", pUser); + rtems_pppd_set_option("password", pPassword); +#endif + + /* set up pppd hooks */ + rtems_pppd_set_hook(RTEMS_PPPD_LINKUP_HOOK, pppdapp_linkup_hook); + rtems_pppd_set_hook(RTEMS_PPPD_LINKDOWN_HOOK, pppdapp_linkdown_hook); + rtems_pppd_set_hook(RTEMS_PPPD_IPUP_HOOK, pppdapp_ipup_hook); + rtems_pppd_set_hook(RTEMS_PPPD_IPDOWN_HOOK, pppdapp_ipdown_hook); +} + +static rtems_task pppdapp(rtems_task_argument arg) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_interval tickspersecond = 0; + rtems_option options; + rtems_event_set in; + rtems_event_set out; + + /* initialize ticks per second */ + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &tickspersecond); + if ( tickspersecond == 0 ) { + /* ensure value is greater than zero */ + tickspersecond = 100; + } + + /* initiate connection */ + pppdapp_setup(); + rtems_pppd_connect(); + + /* enter processing loop */ + in = (RTEMS_EVENT_10 | RTEMS_EVENT_11); + options = (RTEMS_EVENT_ANY | RTEMS_WAIT); + while ( sc == RTEMS_SUCCESSFUL ) { + /* wait for the next event */ + sc = rtems_event_receive(in, options, RTEMS_NO_TIMEOUT, &out); + if ( sc == RTEMS_SUCCESSFUL ) { + /* determine which event was sent */ + if ( out & RTEMS_EVENT_10 ) { + /* ip up recived */ + /* call disconnect function */ + rtems_pppd_disconnect(); + } + if ( out & RTEMS_EVENT_11 ) { + /* ip down recived */ + /* sleep 10 seconds and call connect function */ + rtems_task_wake_after(10*tickspersecond); + rtems_pppd_connect(); + } + } + } + + /* terminate myself */ + rtems_task_delete(RTEMS_SELF); +} + +int pppdapp_initialize(void) +{ + int iReturn = (int)-1; + rtems_status_code status; + rtems_name taskName; + + taskName = rtems_build_name( 'p', 'a', 'p', 'p' ); + status = rtems_task_create(taskName, + CONFIGURE_INIT_TASK_PRIORITY, + CONFIGURE_INIT_TASK_STACK_SIZE, + CONFIGURE_INIT_TASK_INITIAL_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &pppdapp_taskid); + if ( status == RTEMS_SUCCESSFUL ) { + status = rtems_task_start(pppdapp_taskid, pppdapp, 0); + if ( status == RTEMS_SUCCESSFUL ) { + iReturn = (int)0; + } + } + + return ( iReturn ); +} diff --git a/c/src/libnetworking/pppd/example/system.h b/c/src/libnetworking/pppd/example/system.h new file mode 100644 index 0000000000..87678da1b6 --- /dev/null +++ b/c/src/libnetworking/pppd/example/system.h @@ -0,0 +1,42 @@ + +#ifndef SYSTEM_H +#define SYSTEM_H + +#include +#include + +/* functions */ +extern rtems_task Init(rtems_task_argument argument); + +#include + +#define CONFIGURE_HAS_OWN_DEVICE_DRIVER_TABLE +#ifdef CONFIGURE_INIT +rtems_driver_address_table Device_drivers[5] = { + CONSOLE_DRIVER_TABLE_ENTRY, + CLOCK_DRIVER_TABLE_ENTRY, + TTY1_DRIVER_TABLE_ENTRY, + TTY2_DRIVER_TABLE_ENTRY, + {NULL, NULL, NULL, NULL, NULL, NULL} +}; +#endif + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 8 + +#define CONFIGURE_EXECUTIVE_RAM_SIZE (512*1024) +#define CONFIGURE_MAXIMUM_SEMAPHORES 20 +#define CONFIGURE_MAXIMUM_TASKS 20 + +#define CONFIGURE_MICROSECONDS_PER_TICK 10000 + +#define CONFIGURE_INIT_TASK_STACK_SIZE (10*1024) +#define CONFIGURE_INIT_TASK_PRIORITY 120 +#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \ + RTEMS_NO_TIMESLICE | \ + RTEMS_NO_ASR | \ + RTEMS_INTERRUPT_LEVEL(0)) + +#include + +#endif diff --git a/c/src/libnetworking/pppd/fsm.c b/c/src/libnetworking/pppd/fsm.c index 0d50b35c6c..07a8c11f1d 100644 --- a/c/src/libnetworking/pppd/fsm.c +++ b/c/src/libnetworking/pppd/fsm.c @@ -17,10 +17,8 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif -#define log_packet(p, len, prefix, level) +#define RCSID "$Id$" + /* * TODO: * Randomize fsm id on link/init. @@ -30,11 +28,12 @@ #include #include #include -#include #include "pppd.h" #include "fsm.h" +static const char rcsid[] = RCSID; + static void fsm_timeout __P((void *)); static void fsm_rconfreq __P((fsm *, int, u_char *, int)); static void fsm_rconfack __P((fsm *, int, u_char *, int)); @@ -92,8 +91,7 @@ fsm_lowerup(f) break; default: - FSMDEBUG((LOG_INFO, "%s: Up event in state %d!", - PROTO_NAME(f), f->state)); + FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); } } @@ -138,8 +136,7 @@ fsm_lowerdown(f) break; default: - FSMDEBUG((LOG_INFO, "%s: Down event in state %d!", - PROTO_NAME(f), f->state)); + FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); } } @@ -260,8 +257,7 @@ fsm_timeout(arg) case ACKRCVD: case ACKSENT: if (f->retransmits <= 0) { - syslog(LOG_WARNING, "%s: timeout sending Config-Requests", - PROTO_NAME(f)); + warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f)); f->state = STOPPED; if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) (*f->callbacks->finished)(f); @@ -277,8 +273,7 @@ fsm_timeout(arg) break; default: - FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d!", - PROTO_NAME(f), f->state)); + FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); } } @@ -302,27 +297,24 @@ fsm_input(f, inpacket, l) */ inp = inpacket; if (l < HEADERLEN) { - FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.", - f->protocol)); + FSMDEBUG(("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)); + FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); return; } if (len > l) { - FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.", - f->protocol)); + FSMDEBUG(("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.", + FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", f->protocol, f->state)); return; } @@ -371,13 +363,12 @@ fsm_input(f, inpacket, l) static void fsm_rconfreq(f, id, inp, len) fsm *f; - int id; + 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 */ @@ -446,17 +437,12 @@ fsm_rconfack(f, id, inp, len) 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)); + error("Received bad configure-ack: %P", inp, len); return; } f->seen_ack = 1; @@ -511,17 +497,12 @@ fsm_rconfnakrej(f, code, id, inp, len) int (*proc) __P((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)); + error("Received bad configure-nak/rej: %P", inp, len); return; } f->seen_ack = 1; @@ -570,11 +551,6 @@ fsm_rtermreq(f, id, p, len) 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: @@ -583,10 +559,9 @@ fsm_rtermreq(f, id, p, len) 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); + info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); } else - syslog(LOG_INFO, "%s terminated by peer", PROTO_NAME(f)); + info("%s terminated by peer", PROTO_NAME(f)); if (f->callbacks->down) (*f->callbacks->down)(f); /* Inform upper layers */ f->retransmits = 0; @@ -606,8 +581,6 @@ 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); @@ -646,16 +619,13 @@ fsm_rcoderej(f, inp, 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!")); + FSMDEBUG(("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); + warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); if( f->state == ACKRCVD ) f->state = REQSENT; @@ -708,7 +678,7 @@ fsm_protreject(f) break; default: - FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d!", + FSMDEBUG(("%s: Protocol-reject event in state %d!", PROTO_NAME(f), f->state)); } } @@ -759,9 +729,6 @@ fsm_sconfreq(f, retransmit) /* 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)); } @@ -773,7 +740,7 @@ fsm_sconfreq(f, retransmit) void fsm_sdata(f, code, id, data, datalen) fsm *f; - int code, id; + u_char code, id; u_char *data; int datalen; { @@ -792,7 +759,4 @@ fsm_sdata(f, code, id, data, datalen) 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/c/src/libnetworking/pppd/fsm.h b/c/src/libnetworking/pppd/fsm.h index f289429fdc..c94a68e6ce 100644 --- a/c/src/libnetworking/pppd/fsm.h +++ b/c/src/libnetworking/pppd/fsm.h @@ -22,7 +22,7 @@ /* * Packet header = Code, id, length. */ -#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) +#define HEADERLEN 4 /* diff --git a/c/src/libnetworking/pppd/ipcp.c b/c/src/libnetworking/pppd/ipcp.c index 5553d3194d..57245721fa 100644 --- a/c/src/libnetworking/pppd/ipcp.c +++ b/c/src/libnetworking/pppd/ipcp.c @@ -17,9 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" /* * TODO: @@ -27,29 +25,39 @@ #include #include -#include #include #include #include #include #include -/* #include */ +#include #include "pppd.h" #include "fsm.h" #include "ipcp.h" #include "pathnames.h" +static const char rcsid[] = RCSID; + /* 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 */ +bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ + +/* Hook for a plugin to know when IP protocol has come up */ +void (*ip_up_hook) __P((void)) = NULL; + +/* Hook for a plugin to know when IP protocol has come down */ +void (*ip_down_hook) __P((void)) = NULL; + /* 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 */ +static bool usepeerdns; /* Ask peer for DNS addrs */ +static int ipcp_is_up; /* have called np_up() */ /* * Callbacks for fsm code. (CI = Configuration Information) @@ -63,9 +71,6 @@ static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ static void ipcp_up __P((fsm *)); /* We're UP */ static void ipcp_down __P((fsm *)); /* We're DOWN */ -#if 0 -static void ipcp_script __P((fsm *, char *)); /* Run an up/down script */ -#endif static void ipcp_finished __P((fsm *)); /* Don't need lower layer */ fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ @@ -88,6 +93,71 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ "IPCP" /* String name of protocol */ }; +/* + * Command-line options. + */ +static int setvjslots __P((char **)); +static int setdnsaddr __P((char **)); +static int setwinsaddr __P((char **)); + +static option_t ipcp_option_list[] = { + { "noip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP" }, + { "-ip", o_bool, &ipcp_protent.enabled_flag, + "Disable IP and IPCP" }, + { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, + { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, + "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, + { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_A2COPY, + &ipcp_allowoptions[0].cflag }, + { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, + "Disable VJ connection-ID compression", OPT_A2COPY, + &ipcp_allowoptions[0].cflag }, + { "vj-max-slots", 1, setvjslots, + "Set maximum VJ header slots" }, + { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, + "Accept peer's address for us", 1 }, + { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, + "Accept peer's address for it", 1 }, + { "ipparam", o_string, &ipparam, + "Set ip script parameter" }, + { "noipdefault", o_bool, &disable_defaultip, + "Don't use name for default IP adrs", 1 }, + { "ms-dns", 1, setdnsaddr, + "DNS address for the peer's use" }, + { "ms-wins", 1, setwinsaddr, + "Nameserver for SMB over TCP/IP for peer" }, + { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, + "Set timeout for IPCP" }, + { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, + "Set max #xmits for term-reqs" }, + { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, + "Set max #xmits for conf-reqs" }, + { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, + "Set max #conf-naks for IPCP" }, + { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, + "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, + { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_A2COPY, + &ipcp_wantoptions[0].default_route }, + { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, + "disable defaultroute option", OPT_A2COPY, + &ipcp_wantoptions[0].default_route }, + { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, + "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, + { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_A2COPY, + &ipcp_wantoptions[0].proxy_arp }, + { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, + "disable proxyarp option", OPT_A2COPY, + &ipcp_wantoptions[0].proxy_arp }, + { "usepeerdns", o_bool, &usepeerdns, + "Ask peer for DNS address(es)", 1 }, + { NULL } +}; + /* * Protocol entry points from main code. */ @@ -103,6 +173,7 @@ static int ipcp_printpkt __P((u_char *, int, static void ip_check_options __P((void)); static int ip_demand_conf __P((int)); static int ip_active_pkt __P((u_char *, int)); +static void create_resolv __P((u_int32_t, u_int32_t)); struct protent ipcp_protent = { PPP_IPCP, @@ -117,12 +188,14 @@ struct protent ipcp_protent = { NULL, 1, "IPCP", + "IP", + ipcp_option_list, ip_check_options, ip_demand_conf, ip_active_pkt }; -static void ipcp_clear_addrs __P((int)); +static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t)); /* * Lengths of configuration options. @@ -137,7 +210,6 @@ static void ipcp_clear_addrs __P((int)); #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ (x) == CONFNAK ? "NAK" : "REJ") - /* * Make a string representation of a network IP address. */ @@ -147,16 +219,96 @@ 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)); + slprintf(b, sizeof(b), "%I", ipaddr); return b; } +/* + * Option parsing. + */ + +/* + * 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; +} + +/* + * 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 == (u_int32_t) -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 == (u_int32_t) -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); +} + /* * ipcp_init - Initialize IPCP. @@ -182,7 +334,7 @@ ipcp_init(unit) wo->vj_protocol = IPCP_VJ_COMP; wo->maxslotindex = MAX_STATES - 1; /* really max index */ wo->cflag = 1; - ipcp_wantoptions[0].default_route = 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 */ @@ -274,25 +426,31 @@ ipcp_protrej(unit) /* * ipcp_resetci - Reset our CI. + * Called by fsm_sconfreq, Send Configure Request. */ static void ipcp_resetci(f) fsm *f; { ipcp_options *wo = &ipcp_wantoptions[f->unit]; + ipcp_options *go = &ipcp_gotoptions[f->unit]; wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr; - if (wo->ouraddr == 0) + if (wo->ouraddr == 0 || disable_defaultip) wo->accept_local = 1; if (wo->hisaddr == 0) wo->accept_remote = 1; - ipcp_gotoptions[f->unit] = *wo; - cis_received[f->unit] = 0; + wo->req_dns1 = usepeerdns; /* Request DNS addresses from the peer */ + wo->req_dns2 = usepeerdns; + *go = *wo; + if (disable_defaultip) + go->ouraddr = 0; } /* * ipcp_cilen - Return length of our CI. + * Called by fsm_sconfreq, Send Configure Request. */ static int ipcp_cilen(f) @@ -304,6 +462,7 @@ ipcp_cilen(f) #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0) +#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0) /* * First see if we want to change our options to the old @@ -316,26 +475,24 @@ ipcp_cilen(f) } 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 */ + /* use the old style only if the peer did */ + if (ho->neg_vj && ho->old_vj) { 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; - } + 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)); + LENCIVJ(go->neg_vj, go->old_vj) + + LENCIDNS(go->req_dns1) + + LENCIDNS(go->req_dns2)) ; } /* * ipcp_addci - Add our desired CIs to a packet. + * Called by fsm_sconfreq, Send Configure Request. */ static void ipcp_addci(f, ucp, lenp) @@ -380,18 +537,36 @@ ipcp_addci(f, ucp, lenp) neg = 0; \ } +#define ADDCIDNS(opt, neg, addr) \ + if (neg) { \ + if (len >= CILEN_ADDR) { \ + u_int32_t l; \ + PUTCHAR(opt, ucp); \ + PUTCHAR(CILEN_ADDR, ucp); \ + l = ntohl(addr); \ + PUTLONG(l, ucp); \ + len -= CILEN_ADDR; \ + } 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); + ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + *lenp -= len; } /* * ipcp_ackci - Ack our CIs. + * Called by fsm_rconfack, Receive Configure ACK. * * Returns: * 0 - Ack was bad. @@ -460,12 +635,31 @@ ipcp_ackci(f, p, len) } \ } +#define ACKCIDNS(opt, neg, addr) \ + if (neg) { \ + u_int32_t l; \ + if ((len -= CILEN_ADDR) < 0) \ + goto bad; \ + GETCHAR(citype, p); \ + GETCHAR(cilen, p); \ + if (cilen != CILEN_ADDR || citype != opt) \ + goto bad; \ + GETLONG(l, p); \ + cilong = htonl(l); \ + if (addr != 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); + ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); + + ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); + /* * If there are any remaining CIs, then this packet is bad. */ @@ -474,7 +668,7 @@ ipcp_ackci(f, p, len) return (1); bad: - IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!")); + IPCPDEBUG(("ipcp_ackci: received bad Ack!")); return (0); } @@ -482,6 +676,7 @@ bad: * 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. + * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. * * Returns: * 0 - Nak was bad. @@ -497,7 +692,7 @@ ipcp_nakci(f, p, len) u_char cimaxslotindex, cicflag; u_char citype, cilen, *next; u_short cishort; - u_int32_t ciaddr1, ciaddr2, l; + u_int32_t ciaddr1, ciaddr2, l, cidnsaddr; ipcp_options no; /* options we've seen Naks for */ ipcp_options try; /* options to request next time */ @@ -540,6 +735,19 @@ ipcp_nakci(f, p, len) code \ } +#define NAKCIDNS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cidnsaddr = htonl(l); \ + 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. @@ -547,13 +755,9 @@ ipcp_nakci(f, p, len) 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))); } ); @@ -586,6 +790,14 @@ ipcp_nakci(f, p, len) } ); + NAKCIDNS(CI_MS_DNS1, req_dns1, + try.dnsaddr[0] = cidnsaddr; + ); + + NAKCIDNS(CI_MS_DNS2, req_dns2, + try.dnsaddr[1] = cidnsaddr; + ); + /* * There may be remaining CIs, if the peer is requesting negotiation * on an option that we didn't include in our request packet. @@ -638,12 +850,9 @@ ipcp_nakci(f, p, len) 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 there are any remaining options, we ignore them. */ if (f->state != OPENED) *go = try; @@ -651,13 +860,14 @@ ipcp_nakci(f, p, len) return 1; bad: - IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!")); + IPCPDEBUG(("ipcp_nakci: received bad Nak!")); return 0; } /* * ipcp_rejci - Reject some of our CIs. + * Callback from fsm_rconfnakrej. */ static int ipcp_rejci(f, p, len) @@ -722,12 +932,33 @@ ipcp_rejci(f, p, len) try.neg = 0; \ } +#define REJCIDNS(opt, neg, dnsaddr) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + u_int32_t l; \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + cilong = htonl(l); \ + /* Check rejected value. */ \ + if (cilong != dnsaddr) \ + 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); + REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); + + REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); + /* * If there are any remaining CIs, then this packet is bad. */ @@ -741,13 +972,14 @@ ipcp_rejci(f, p, len) return 1; bad: - IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!")); + IPCPDEBUG(("ipcp_rejci: received bad Reject!")); return 0; } /* * ipcp_reqci - Check the peer's requested CIs and send appropriate response. + * Callback from fsm_rconfreq, Receive Configure Request * * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified * appropriately. If reject_if_disagree is non-zero, doesn't return @@ -776,8 +1008,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) u_char maxslotindex, cflag; int d; - cis_received[f->unit] = 1; - /* * Reset all his options. */ @@ -793,7 +1023,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) 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!")); + IPCPDEBUG(("ipcp_reqci: bad CI length!")); orc = CONFREJ; /* Reject bad CI */ cilen = l; /* Reject till end of packet */ l = 0; /* Don't loop again */ @@ -806,7 +1036,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) 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 */ @@ -821,7 +1050,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) */ 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; @@ -845,7 +1073,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) */ 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; @@ -866,8 +1093,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) break; case CI_ADDR: - IPCPDEBUG((LOG_INFO, "ipcp: received ADDR ")); - if (!ao->neg_addr || cilen != CILEN_ADDR) { /* Check CI length */ orc = CONFREJ; /* Reject CI */ @@ -882,7 +1107,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) */ 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; @@ -908,7 +1132,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) 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 || @@ -929,7 +1152,6 @@ ipcp_reqci(f, inp, len, reject_if_disagree) 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 || @@ -947,14 +1169,12 @@ ipcp_reqci(f, inp, len, reject_if_disagree) 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))) { @@ -994,10 +1214,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) 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 */ @@ -1050,7 +1267,7 @@ endswitch: } *len = ucp - inp; /* Compute output length */ - IPCPDEBUG((LOG_INFO, "ipcp: returning Configure-%s", CODENAME(rc))); + IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); return (rc); /* Return final code */ } @@ -1070,7 +1287,7 @@ ip_check_options() * Default our local IP address based on our hostname. * If local IP address already given, don't bother. */ - if (wo->ouraddr == 0 && !disable_defaultip) { + if (wo->ouraddr == 0) { /* * Look up our hostname (possibly with domain name appended) * and take the first IP address as our local IP address. @@ -1083,7 +1300,6 @@ ip_check_options() wo->ouraddr = local; } } - } @@ -1097,6 +1313,17 @@ ip_demand_conf(u) { ipcp_options *wo = &ipcp_wantoptions[u]; + if (wo->hisaddr == 0) { + /* make up an arbitrary address for the peer */ + wo->hisaddr = htonl(0x0a707070 + pppifunit); + wo->accept_remote = 1; + } + if (wo->ouraddr == 0) { + /* make up an arbitrary address for us */ + wo->ouraddr = htonl(0x0a404040 + pppifunit); + wo->accept_local = 1; + disable_defaultip = 1; /* don't tell the peer this address */ + } if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr))) return 0; if (!sifup(u)) @@ -1110,8 +1337,8 @@ ip_demand_conf(u) 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)); + notice("local IP address %I", wo->ouraddr); + notice("remote IP address %I", wo->hisaddr); return 1; } @@ -1122,9 +1349,6 @@ ip_demand_conf(u) * * Configure the IP network interface appropriately and bring it up. */ -#define script_setenv(a,b) - - static void ipcp_up(f) fsm *f; @@ -1134,8 +1358,7 @@ ipcp_up(f) 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")); + IPCPDEBUG(("ipcp: up")); /* * We must have a non-zero IP address for both ends of the link. @@ -1144,24 +1367,25 @@ ipcp_up(f) ho->hisaddr = wo->hisaddr; if (ho->hisaddr == 0) { - syslog(LOG_ERR, "Could not determine remote IP address"); + error("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"); + error("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)); -*/ + + if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { + create_resolv(go->dnsaddr[0], go->dnsaddr[1]); + } + /* * 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)); + error("Peer is not authorized to use remote address %I", ho->hisaddr); ipcp_close(f->unit, "Unauthorized remote IP address"); return; } @@ -1174,7 +1398,42 @@ ipcp_up(f) * 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) { + ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr); + if (go->ouraddr != wo->ouraddr) { + warn("Local IP address changed to %I", go->ouraddr); + wo->ouraddr = go->ouraddr; + } + if (ho->hisaddr != wo->hisaddr) { + warn("Remote IP address changed to %I", ho->hisaddr); + wo->hisaddr = ho->hisaddr; + } + + /* Set the interface to the new addresses */ + mask = GetMask(go->ouraddr); + if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { + if (debug) + warn("Interface configuration 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. */ @@ -1182,7 +1441,8 @@ ipcp_up(f) #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { - IPCPDEBUG((LOG_WARNING, "sifaddr failed")); + if (debug) + warn("Interface configuration failed"); ipcp_close(f->unit, "Interface configuration failed"); return; } @@ -1190,14 +1450,16 @@ ipcp_up(f) /* bring the interface up for IP */ if (!sifup(f->unit)) { - IPCPDEBUG((LOG_WARNING, "sifup failed")); + if (debug) + warn("Interface failed to come up"); 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")); + if (debug) + warn("Interface configuration failed"); ipcp_close(f->unit, "Interface configuration failed"); return; } @@ -1214,23 +1476,21 @@ ipcp_up(f) 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)); + ipcp_wantoptions[0].ouraddr = go->ouraddr; + + notice("local IP address %I", go->ouraddr); + notice("remote IP address %I", ho->hisaddr); + if (go->dnsaddr[0]) + notice("primary DNS address %I", go->dnsaddr[0]); + if (go->dnsaddr[1]) + notice("secondary DNS address %I", go->dnsaddr[1]); } - /* - * Execute the ip-up script, like this: - * /etc/ppp/ip-up interface tty speed local-IP remote-IP - */ - { -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus *stat; - stat=LockSTBSystemParam(); - stat->ConnectionStatus=Connected; - UnlockSTBSystemParam(); -#endif - } + np_up(f->unit, PPP_IP); + ipcp_is_up = 1; + + if (ip_up_hook) + ip_up_hook(); } @@ -1244,27 +1504,30 @@ static void ipcp_down(f) fsm *f; { - IPCPDEBUG((LOG_INFO, "ipcp: down")); - np_down(f->unit, PPP_IP); + IPCPDEBUG(("ipcp: down")); + /* XXX a bit IPv4-centric here, we only need to get the stats + * before the interface is marked down. */ + update_link_stats(f->unit); + if (ip_down_hook) + ip_down_hook(); + if (ipcp_is_up) { + ipcp_is_up = 0; + 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 { + sifnpmode(f->unit, PPP_IP, NPMODE_DROP); sifdown(f->unit); - ipcp_clear_addrs(f->unit); - - /* Execute the ip-down script */ - { -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus *stat; - stat=LockSTBSystemParam(); - stat->ConnectionStatus=NotConnected; - UnlockSTBSystemParam(); -#endif - } + ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr, + ipcp_hisoptions[f->unit].hisaddr); + } } @@ -1273,13 +1536,11 @@ ipcp_down(f) * proxy arp entries, etc. */ static void -ipcp_clear_addrs(unit) +ipcp_clear_addrs(unit, ouraddr, hisaddr) int unit; + u_int32_t ouraddr; /* local address */ + u_int32_t hisaddr; /* remote address */ { - 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; @@ -1302,35 +1563,32 @@ ipcp_finished(f) np_finished(f->unit, PPP_IP); } - -#if 0 /* - * ipcp_script - Execute a script with arguments - * interface-name tty-name speed local-IP remote-IP. + * create_resolv - create the replacement resolv.conf file */ static void -ipcp_script(f, script) - fsm *f; - char *script; +create_resolv(peerdns1, peerdns2) + u_int32_t peerdns1, peerdns2; { - 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); + FILE *f; + + f = fopen(_PATH_RESOLV, "w"); + if (f == NULL) { + error("Failed to create %s: %m", _PATH_RESOLV); + return; + } + + if (peerdns1) + fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1)); + + if (peerdns2) + fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2)); + + if (ferror(f)) + error("Write failed to %s: %m", _PATH_RESOLV); + + fclose(f); } -#endif /* * ipcp_printpkt - print the contents of an IPCP packet. @@ -1372,7 +1630,7 @@ ipcp_printpkt(p, plen, printer, arg) case CONFACK: case CONFNAK: case CONFREJ: - + /* print option list */ while (len >= 2) { GETCHAR(code, p); GETCHAR(olen, p); @@ -1421,7 +1679,8 @@ ipcp_printpkt(p, plen, printer, arg) case CI_MS_DNS2: p += 2; GETLONG(cilong, p); - printer(arg, "ms-dns %I", htonl(cilong)); + printer(arg, "ms-dns%d %I", code - CI_MS_DNS1 + 1, + htonl(cilong)); break; case CI_MS_WINS1: case CI_MS_WINS2: @@ -1442,13 +1701,14 @@ ipcp_printpkt(p, plen, printer, arg) case TERMREQ: if (len > 0 && *p >= ' ' && *p < 0x7f) { printer(arg, " "); - print_string(p, len, 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); diff --git a/c/src/libnetworking/pppd/ipcp.h b/c/src/libnetworking/pppd/ipcp.h index e2c7eb44db..8c5aca861d 100644 --- a/c/src/libnetworking/pppd/ipcp.h +++ b/c/src/libnetworking/pppd/ipcp.h @@ -43,17 +43,20 @@ /* 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. */ + bool neg_addr; /* Negotiate IP Address? */ + bool old_addrs; /* Use old (IP-Addresses) option? */ + bool req_addr; /* Ask peer to send IP address? */ + bool default_route; /* Assign default route through interface? */ + bool proxy_arp; /* Make proxy ARP entry for peer? */ + bool neg_vj; /* Van Jacobson Compression? */ + bool old_vj; /* use old (short) form of VJ option? */ + bool accept_local; /* accept peer's value for ouraddr */ + bool accept_remote; /* accept peer's value for hisaddr */ + bool req_dns1; /* Ask peer to send primary DNS address? */ + bool req_dns2; /* Ask peer to send secondary DNS address? */ + int vj_protocol; /* protocol value to use in VJ option */ + int maxslotindex; /* values for RFC1332 VJ compression neg. */ + bool cflag; u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ u_int32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ u_int32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ diff --git a/c/src/libnetworking/pppd/ipxcp.c b/c/src/libnetworking/pppd/ipxcp.c index d55ace569e..4e408a00f9 100644 --- a/c/src/libnetworking/pppd/ipxcp.c +++ b/c/src/libnetworking/pppd/ipxcp.c @@ -18,9 +18,8 @@ */ #ifdef IPX_CHANGE -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif + +#define RCSID "$Id$" /* * TODO: @@ -28,7 +27,8 @@ #include #include -#include +#include +#include #include #include #include @@ -37,6 +37,9 @@ #include "fsm.h" #include "ipxcp.h" #include "pathnames.h" +#include "magic.h" + +static const char rcsid[] = RCSID; /* global vars */ ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */ @@ -61,7 +64,7 @@ static int ipxcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ static int ipxcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ static void ipxcp_up __P((fsm *)); /* We're UP */ static void ipxcp_down __P((fsm *)); /* We're DOWN */ -static void ipxcp_script __P((fsm *, char *)); /* Run an up/down script */ +static void ipxcp_finished __P((fsm *)); /* Don't need lower layer */ fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */ @@ -76,13 +79,57 @@ static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */ 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 */ + ipxcp_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 */ "IPXCP" /* String name of protocol */ }; +/* + * Command-line options. + */ +static int setipxnode __P((char **)); +static int setipxname __P((char **)); + +static option_t ipxcp_option_list[] = { + { "ipx", o_bool, &ipxcp_protent.enabled_flag, + "Enable IPXCP (and IPX)", 1 }, + { "+ipx", o_bool, &ipxcp_protent.enabled_flag, + "Enable IPXCP (and IPX)", 1 }, + { "noipx", o_bool, &ipxcp_protent.enabled_flag, + "Disable IPXCP (and IPX)" }, + { "-ipx", o_bool, &ipxcp_protent.enabled_flag, + "Disable IPXCP (and IPX)" } , + { "ipx-network", o_uint32, &ipxcp_wantoptions[0].our_network, + "Set our IPX network number", 0, &ipxcp_wantoptions[0].neg_nn }, + { "ipxcp-accept-network", o_bool, &ipxcp_wantoptions[0].accept_network, + "Accept peer IPX network number", 1, + &ipxcp_allowoptions[0].accept_network }, + { "ipx-node", o_special, setipxnode, + "Set IPX node number" }, + { "ipxcp-accept-local", o_bool, &ipxcp_wantoptions[0].accept_local, + "Accept our IPX address", 1, + &ipxcp_allowoptions[0].accept_local }, + { "ipxcp-accept-remote", o_bool, &ipxcp_wantoptions[0].accept_remote, + "Accept peer's IPX address", 1, + &ipxcp_allowoptions[0].accept_remote }, + { "ipx-routing", o_int, &ipxcp_wantoptions[0].router, + "Set IPX routing proto number", 0, + &ipxcp_wantoptions[0].neg_router }, + { "ipx-router-name", o_special, setipxname, + "Set IPX router name" }, + { "ipxcp-restart", o_int, &ipxcp_fsm[0].timeouttime, + "Set timeout for IPXCP" }, + { "ipxcp-max-terminate", o_int, &ipxcp_fsm[0].maxtermtransmits, + "Set max #xmits for IPXCP term-reqs" }, + { "ipxcp-max-configure", o_int, &ipxcp_fsm[0].maxconfreqtransmits, + "Set max #xmits for IPXCP conf-reqs" }, + { "ipxcp-max-failure", o_int, &ipxcp_fsm[0].maxnakloops, + "Set max #conf-naks for IPXCP" }, + { NULL } +}; + /* * Protocol entry points. */ @@ -110,6 +157,8 @@ struct protent ipxcp_protent = { NULL, 0, "IPXCP", + "IPX", + ipxcp_option_list, NULL, NULL, NULL @@ -130,6 +179,10 @@ struct protent ipxcp_protent = { #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ (x) == CONFNAK ? "NAK" : "REJ") +static int ipxcp_is_up; + +static char *ipx_ntoa __P((u_int32_t)); + /* Used in printing the node number */ #define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5] @@ -146,7 +199,7 @@ short int internal; { short int external; - if (internal & IPX_NONE) + if (internal & BIT(IPX_NONE) ) external = IPX_NONE; else external = RIP_SAP; @@ -158,16 +211,97 @@ short int internal; * Make a string representation of a network IP address. */ -char * +static char * ipx_ntoa(ipxaddr) u_int32_t ipxaddr; { static char b[64]; - sprintf(b, "%x", ipxaddr); + slprintf(b, sizeof(b), "%x", ipxaddr); return b; } +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 +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; +} + /* * ipxcp_init - Initialize IPXCP. */ @@ -532,9 +666,8 @@ ipxcp_ackci(f, p, len) 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); + if (len > 0) + ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router); /* * This is the end of the record. */ @@ -544,7 +677,7 @@ ipxcp_ackci(f, p, len) /* * The frame is invalid */ - IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!")); + IPXCPDEBUG(("ipxcp_ackci: received bad Ack!")); return (0); } @@ -588,7 +721,6 @@ ipxcp_nakci(f, p, len) 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; @@ -598,10 +730,6 @@ ipxcp_nakci(f, p, len) 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); @@ -629,8 +757,6 @@ ipxcp_nakci(f, p, len) 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. */ @@ -645,10 +771,6 @@ ipxcp_nakci(f, p, len) 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". @@ -662,6 +784,7 @@ ipxcp_nakci(f, p, len) /* * OK, the Nak is good. Now we can update state. + * If there are any options left, we ignore them. */ if (f->state != OPENED) *go = try; @@ -669,7 +792,7 @@ ipxcp_nakci(f, p, len) return 1; bad: - IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!")); + IPXCPDEBUG(("ipxcp_nakci: received bad Nak!")); return 0; } @@ -699,7 +822,6 @@ ipxcp_rejci(f, p, len) GETLONG(cilong, p); \ if (cilong != val) \ break; \ - IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \ neg = 0; \ } @@ -721,14 +843,13 @@ ipxcp_rejci(f, p, len) }\ 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(gpt, neg) \ +#define REJCIVOID(opt, neg) \ if (neg && p[0] == opt) { \ if ((len -= CILEN_VOID) < 0) \ break; \ @@ -736,7 +857,6 @@ ipxcp_rejci(f, p, len) GETCHAR(cilen, p); \ if (cilen != CILEN_VOID || citype != opt) \ break; \ - IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \ neg = 0; \ } @@ -753,7 +873,6 @@ ipxcp_rejci(f, p, len) GETSHORT(cishort, p); \ if (cishort != to_external (val) || cishort == RIP_SAP) \ break; \ - IPXCPDEBUG((LOG_INFO, "ipxcp_rejci short opt %d", opt)); \ neg = 0; \ } /* @@ -780,7 +899,7 @@ ipxcp_rejci(f, p, len) /* * The frame is invalid at this point. */ - IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!")); + IPXCPDEBUG(("ipxcp_rejci: received bad Reject!")); return 0; } @@ -823,7 +942,7 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) 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!")); + IPXCPDEBUG(("ipxcp_reqci: bad CI length!")); orc = CONFREJ; /* Reject bad CI */ cilen = l; /* Reject till end of packet */ l = 0; /* Don't loop again */ @@ -839,8 +958,6 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) * 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 ) { @@ -848,7 +965,6 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) 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) { @@ -885,8 +1001,6 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) * 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 ) { @@ -944,7 +1058,6 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) * 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; /* @@ -959,9 +1072,6 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) } GETSHORT (cishort, p); - IPXCPDEBUG((LOG_INFO, - "Remote router protocol number 0x%04x", - cishort)); if (wo->neg_router == 0) { wo->neg_router = 1; @@ -1006,7 +1116,6 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) * 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)) @@ -1024,7 +1133,6 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) * This is advisorary. */ case IPX_COMPLETE: - IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request")); if (cilen != CILEN_COMPLETE) orc = CONFREJ; else { @@ -1036,14 +1144,10 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) * 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 */ @@ -1099,7 +1203,7 @@ endswitch: } *len = ucp - inp; /* Compute output length */ - IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc))); + IPXCPDEBUG(("ipxcp: returning Configure-%s", CODENAME(rc))); return (rc); /* Return final code */ } @@ -1115,7 +1219,7 @@ ipxcp_up(f) { int unit = f->unit; - IPXCPDEBUG((LOG_INFO, "ipxcp: up")); + IPXCPDEBUG(("ipxcp: up")); /* The default router protocol is RIP/SAP. */ if (ho->router == 0) @@ -1136,7 +1240,8 @@ ipxcp_up(f) if (zero_node (go->our_node)) { static char errmsg[] = "Could not determine local IPX node address"; - IPXCPDEBUG((LOG_ERR, errmsg)); + if (debug) + error(errmsg); ipxcp_close(f->unit, errmsg); return; } @@ -1147,31 +1252,30 @@ ipxcp_up(f) if (go->network == 0) { static char errmsg[] = "Can not determine network number"; - IPXCPDEBUG((LOG_ERR, errmsg)); + if (debug) + error(errmsg); ipxcp_close (unit, errmsg); return; } /* bring the interface up */ if (!sifup(unit)) { - IPXCPDEBUG((LOG_WARNING, "sifup failed")); + if (debug) + warn("sifup failed (IPX)"); ipxcp_close(unit, "Interface configuration failed"); return; } + ipxcp_is_up = 1; /* set the network number for IPX */ if (!sipxfaddr(unit, go->network, go->our_node)) { - IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed")); + if (debug) + warn("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); + np_up(f->unit, PPP_IPX); } /* @@ -1185,83 +1289,29 @@ static void ipxcp_down(f) fsm *f; { - IPXCPDEBUG((LOG_INFO, "ipxcp: down")); + IPXCPDEBUG(("ipxcp: down")); - cipxfaddr (f->unit); + if (!ipxcp_is_up) + return; + ipxcp_is_up = 0; + np_down(f->unit, PPP_IPX); + cipxfaddr(f->unit); + sifnpmode(f->unit, PPP_IPX, NPMODE_DROP); 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. + * ipxcp_finished - possibly shut down the lower layers. */ static void -ipxcp_script(f, script) +ipxcp_finished(f) 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); + np_finished(f->unit, PPP_IPX); } + /* * ipxcp_printpkt - print the contents of an IPXCP packet. */ diff --git a/c/src/libnetworking/pppd/ipxcp.h b/c/src/libnetworking/pppd/ipxcp.h index 139a7260b3..47f680d70c 100644 --- a/c/src/libnetworking/pppd/ipxcp.h +++ b/c/src/libnetworking/pppd/ipxcp.h @@ -35,22 +35,22 @@ #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? */ + bool neg_node; /* Negotiate IPX node number? */ + bool req_node; /* 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 */ + bool neg_nn; /* Negotiate IPX network number? */ + bool req_nn; /* 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 */ + bool neg_name; /* Negotiate IPX router name */ + bool neg_complete; /* Negotiate completion */ + bool neg_router; /* 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 */ + bool accept_local; /* accept peer's value for ournode */ + bool accept_remote; /* accept peer's value for hisnode */ + bool accept_network; /* accept network number */ - int tried_nlsp : 1; /* I have suggested NLSP already */ - int tried_rip : 1; /* I have suggested RIP/SAP already */ + bool tried_nlsp; /* I have suggested NLSP already */ + bool tried_rip; /* I have suggested RIP/SAP already */ u_int32_t his_network; /* base network number */ u_int32_t our_network; /* our value for network number */ diff --git a/c/src/libnetworking/pppd/lcp.c b/c/src/libnetworking/pppd/lcp.c index e58b3dcba2..781f5569ad 100644 --- a/c/src/libnetworking/pppd/lcp.c +++ b/c/src/libnetworking/pppd/lcp.c @@ -17,9 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$"; /* * TODO: @@ -27,13 +25,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#include #include "pppd.h" #include "fsm.h" @@ -41,6 +33,83 @@ #include "chap.h" #include "magic.h" +static const char rcsid[] = RCSID; + +/* + * LCP-related command-line options. + */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +bool lax_recv = 0; /* accept control chars in asyncmap */ + +static int setescape __P((char **)); + +static option_t lcp_option_list[] = { + /* LCP options */ + { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_A2COPY, &lcp_allowoptions[0].neg_accompression }, + { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, + "Disable address/control compression", + OPT_A2COPY, &lcp_allowoptions[0].neg_accompression }, + { "default-asyncmap", o_bool, &lcp_wantoptions[0].neg_asyncmap, + "Disable asyncmap negotiation", + OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap }, + { "-am", o_bool, &lcp_wantoptions[0].neg_asyncmap, + "Disable asyncmap negotiation", + OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap }, + { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, + "Set asyncmap (for received packets)", + OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber }, + { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, + "Disable magic number negotiation (looped-back line detection)", + OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber }, + { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_A2COPY, &lcp_allowoptions[0].neg_mru }, + { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, + "Disable MRU negotiation (use default 1500)", + OPT_A2COPY, &lcp_allowoptions[0].neg_mru }, + { "mru", o_int, &lcp_wantoptions[0].mru, + "Set MRU (maximum received packet size) for negotiation", + 0, &lcp_wantoptions[0].neg_mru }, + { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression }, + { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, + "Disable protocol field compression", + OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression }, + { "-p", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", 1 }, + { "passive", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", 1 }, + { "silent", o_bool, &lcp_wantoptions[0].silent, + "Set silent mode", 1 }, + { "escape", o_special, setescape, + "List of character codes to escape on transmission" }, + { "lcp-echo-failure", o_int, &lcp_echo_fails, + "Set number of consecutive echo failures to indicate link failure" }, + { "lcp-echo-interval", o_int, &lcp_echo_interval, + "Set time in seconds between LCP echo requests" }, + { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, + "Set time in seconds between LCP retransmissions" }, + { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, + "Set maximum number of LCP terminate-request transmissions" }, + { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, + "Set maximum number of LCP configure-request transmissions" }, + { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, + "Set limit on number of LCP configure-naks" }, + { "receive-all", o_bool, &lax_recv, + "Accept all received control characters", 1 }, + {NULL} +}; + /* global vars */ fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ @@ -49,9 +118,9 @@ 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 int lcp_echos_pending = 0; /* Number of outstanding echo msgs */ +static int lcp_echo_number = 0; /* ID number of next echo frame */ +static int lcp_echo_timer_running = 0; /* set if a timer is running */ static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ @@ -127,6 +196,8 @@ struct protent lcp_protent = { 1, "LCP", NULL, + lcp_option_list, + NULL, NULL, NULL }; @@ -138,16 +209,47 @@ int lcp_loopbackfail = DEFLOOPBACKFAIL; */ #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_SHORT 4 /* CILEN_VOID + 2 */ +#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */ +#define CILEN_LONG 6 /* CILEN_VOID + 4 */ +#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */ #define CILEN_CBCP 3 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \ (x) == CONFNAK ? "NAK" : "REJ") +/* + * 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 || 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; +} + /* * lcp_init - Initialize LCP. */ @@ -171,7 +273,7 @@ lcp_init(unit) implementations */ wo->neg_mru = 1; wo->mru = DEFMRU; - wo->neg_asyncmap = 0; + wo->neg_asyncmap = 1; wo->asyncmap = 0; wo->neg_chap = 0; /* Set to 1 on server */ wo->neg_upap = 0; /* Set to 1 on server */ @@ -234,7 +336,7 @@ lcp_close(unit, reason) fsm *f = &lcp_fsm[unit]; if (phase != PHASE_DEAD) - phase = PHASE_TERMINATE; + new_phase(PHASE_TERMINATE); if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) { /* * This action is not strictly according to the FSM in RFC1548, @@ -266,7 +368,7 @@ lcp_lowerup(unit) */ ppp_set_xaccm(unit, xmit_accm[unit]); ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0); - ppp_recv_config(unit, PPP_MRU, 0xffffffff, + ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff), wo->neg_pcompression, wo->neg_accompression); peer_mru[unit] = PPP_MRU; lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0]; @@ -321,7 +423,6 @@ lcp_extcode(f, code, id, inp, len) 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); @@ -356,27 +457,19 @@ lcp_rprotrej(f, inp, len) 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!")); + if (len < 2) { + LCPDEBUG(("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)); + LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); return; } @@ -389,8 +482,7 @@ lcp_rprotrej(f, inp, len) return; } - syslog(LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x", - prot); + warn("Protocol-Reject for unsupported protocol 0x%x", prot); } @@ -405,8 +497,7 @@ lcp_protrej(unit) /* * Can't reject LCP! */ - LCPDEBUG((LOG_WARNING, - "lcp_protrej: Received Protocol-Reject for LCP!")); + error("Received Protocol-Reject for LCP!"); fsm_protreject(&lcp_fsm[unit]); } @@ -541,8 +632,7 @@ lcp_addci(f, ucp, lenp) if (ucp - start_ucp != *lenp) { /* this should never happen, because peer_mtu should be 1500 */ - syslog(LOG_ERR, "Bug in lcp_addci: wrong length") -; + error("Bug in lcp_addci: wrong length"); } } @@ -671,7 +761,7 @@ lcp_ackci(f, p, len) goto bad; return (1); bad: - LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!")); + LCPDEBUG(("lcp_acki: received bad Ack!")); return (0); } @@ -829,11 +919,18 @@ lcp_nakci(f, p, len) 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 + * algorithm. If they can't do MD5, we can ask for M$-CHAP + * if we support it, otherwise we'll have to stop * asking for CHAP. */ - if (cichar != go->chap_mdtype) - try.neg_chap = 0; + if (cichar != go->chap_mdtype) { +#ifdef CHAPMS + if (cichar == CHAP_MICROSOFT) + go->chap_mdtype = CHAP_MICROSOFT; + else +#endif /* CHAPMS */ + try.neg_chap = 0; + } } else { /* * Stop asking for PAP if we were asking for it. @@ -957,18 +1054,16 @@ lcp_nakci(f, p, len) 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 there are any options left we ignore them. */ if (f->state != OPENED) { if (looped_back) { if (++try.numloops >= lcp_loopbackfail) { - syslog(LOG_NOTICE, "Serial line is looped back."); + notice("Serial line is looped back."); lcp_close(f->unit, "Loopback detected"); + status = EXIT_LOOPBACK; } } else try.numloops = 0; @@ -978,7 +1073,7 @@ lcp_nakci(f, p, len) return 1; bad: - LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!")); + LCPDEBUG(("lcp_nakci: received bad Nak!")); return 0; } @@ -1019,7 +1114,6 @@ lcp_rejci(f, p, len) 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 && \ @@ -1033,7 +1127,6 @@ lcp_rejci(f, p, len) 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 && \ @@ -1049,7 +1142,6 @@ lcp_rejci(f, p, len) 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 && \ @@ -1063,7 +1155,6 @@ lcp_rejci(f, p, len) 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 && \ @@ -1078,7 +1169,6 @@ lcp_rejci(f, p, len) 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 && \ @@ -1092,7 +1182,6 @@ lcp_rejci(f, p, len) 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); @@ -1120,7 +1209,7 @@ lcp_rejci(f, p, len) return 1; bad: - LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!")); + LCPDEBUG(("lcp_rejci: received bad Reject!")); return 0; } @@ -1170,7 +1259,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) 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!")); + LCPDEBUG(("lcp_reqci: bad CI length!")); orc = CONFREJ; /* Reject bad CI */ cilen = l; /* Reject till end of packet */ l = 0; /* Don't loop again */ @@ -1184,14 +1273,12 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) 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. @@ -1210,14 +1297,12 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) 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 @@ -1235,7 +1320,6 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; case CI_AUTHTYPE: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE")); if (cilen < CILEN_SHORT || !(ao->neg_upap || ao->neg_chap)) { /* @@ -1245,10 +1329,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; } GETSHORT(cishort, p); - LCPDEBUG((LOG_INFO, "(%x)", cishort)); /* - * Authtype must be UPAP or CHAP. + * Authtype must be PAP or CHAP. * * Note: if both ao->neg_upap and ao->neg_chap are set, * and the peer sends a Configure-Request with two @@ -1261,8 +1344,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) 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...")); + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); orc = CONFREJ; break; } @@ -1272,6 +1354,8 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) PUTCHAR(CILEN_CHAP, nakp); PUTSHORT(PPP_CHAP, nakp); PUTCHAR(ao->chap_mdtype, nakp); + /* XXX if we can do CHAP_MICROSOFT as well, we should + probably put in another option saying so */ break; } ho->neg_upap = 1; @@ -1280,8 +1364,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) 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...")); + LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); orc = CONFREJ; break; } @@ -1328,7 +1411,6 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; case CI_QUALITY: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY")); if (!ao->neg_lqr || cilen != CILEN_LQR) { orc = CONFREJ; @@ -1337,7 +1419,6 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) GETSHORT(cishort, p); GETLONG(cilong, p); - LCPDEBUG((LOG_INFO, "(%x %x)", cishort, (unsigned int) cilong)); /* * Check the protocol and the reporting period. @@ -1354,14 +1435,12 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) 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. @@ -1381,7 +1460,6 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) case CI_PCOMPRESSION: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION")); if (!ao->neg_pcompression || cilen != CILEN_VOID) { orc = CONFREJ; @@ -1391,7 +1469,6 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; case CI_ACCOMPRESSION: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION")); if (!ao->neg_accompression || cilen != CILEN_VOID) { orc = CONFREJ; @@ -1401,14 +1478,12 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; default: - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d", - citype)); + LCPDEBUG(("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 */ @@ -1454,7 +1529,7 @@ endswitch: break; } - LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc))); + LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); return (rc); /* Return final code */ } @@ -1486,7 +1561,7 @@ lcp_up(f) (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), + (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), go->neg_pcompression, go->neg_accompression); if (ho->neg_mru) @@ -1584,7 +1659,7 @@ lcp_printpkt(p, plen, printer, arg) case CONFACK: case CONFNAK: case CONFREJ: - + /* print option list */ while (len >= 2) { GETCHAR(code, p); GETCHAR(olen, p); @@ -1621,6 +1696,20 @@ lcp_printpkt(p, plen, printer, arg) break; case PPP_CHAP: printer(arg, "chap"); + if (p < optend) { + switch (*p) { + case CHAP_DIGEST_MD5: + printer(arg, " MD5"); + ++p; + break; +#ifdef CHAPMS + case CHAP_MICROSOFT: + printer(arg, " m$oft"); + ++p; + break; +#endif + } + } break; default: printer(arg, "0x%x", cishort); @@ -1645,7 +1734,7 @@ lcp_printpkt(p, plen, printer, arg) if (olen >= CILEN_CHAR) { p += 2; printer(arg, "callback "); - GETSHORT(cishort, p); + GETCHAR(cishort, p); switch (cishort) { case CBCP_OPT: printer(arg, "CBCP"); @@ -1705,7 +1794,7 @@ lcp_printpkt(p, plen, printer, arg) break; } - + /* print the rest of the bytes in the packet */ for (; len > 0; --len) { GETCHAR(code, p); printer(arg, " %.2x", code); @@ -1723,9 +1812,10 @@ 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."); + info("No response to %d echo-requests", lcp_echos_pending); + notice("Serial link appears to be disconnected."); lcp_close(f->unit, "Peer not responding"); + status = EXIT_PEER_DEAD; } } @@ -1738,11 +1828,14 @@ LcpEchoCheck (f) fsm *f; { LcpSendEchoRequest (f); + if (f->state != OPENED) + return; /* * Start the timer for the next interval. */ - assert (lcp_echo_timer_running==0); + if (lcp_echo_timer_running) + warn("assertion lcp_echo_timer_running==0 failed"); TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval); lcp_echo_timer_running = 1; } @@ -1768,19 +1861,21 @@ LcpEchoTimeout (arg) static void lcp_received_echo_reply (f, id, inp, len) fsm *f; - int id; u_char *inp; int len; + 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); + dbglog("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!"); + warn("appear to have received our own echo-reply!"); return; } diff --git a/c/src/libnetworking/pppd/lcp.h b/c/src/libnetworking/pppd/lcp.h index 42260f3a63..16ba4cc44b 100644 --- a/c/src/libnetworking/pppd/lcp.h +++ b/c/src/libnetworking/pppd/lcp.h @@ -44,19 +44,19 @@ * 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 */ + bool passive; /* Don't die if we don't get a response */ + bool silent; /* Wait for the other end to start first */ + bool restart; /* Restart vs. exit after close */ + bool neg_mru; /* Negotiate the MRU? */ + bool neg_asyncmap; /* Negotiate the async map? */ + bool neg_upap; /* Ask for UPAP authentication? */ + bool neg_chap; /* Ask for CHAP authentication? */ + bool neg_magicnumber; /* Ask for magic number? */ + bool neg_pcompression; /* HDLC Protocol Field Compression? */ + bool neg_accompression; /* HDLC Address/Control Field Compression? */ + bool neg_lqr; /* Negotiate use of Link Quality Reports */ + bool neg_cbcp; /* Negotiate use of CBCP */ + int 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; diff --git a/c/src/libnetworking/pppd/magic.c b/c/src/libnetworking/pppd/magic.c index 67d6b6ca90..c571ef792e 100644 --- a/c/src/libnetworking/pppd/magic.c +++ b/c/src/libnetworking/pppd/magic.c @@ -17,19 +17,19 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" #include -#include #include +#include #include #include #include "pppd.h" #include "magic.h" +static const char rcsid[] = RCSID; + extern long mrand48 __P((void)); extern void srand48 __P((long)); @@ -64,7 +64,7 @@ magic() * Substitute procedures for those systems which don't have * drand48 et al. */ -/* #include */ + double drand48() { @@ -83,4 +83,3 @@ long seedval; { srand((int)seedval); } - diff --git a/c/src/libnetworking/pppd/main.c b/c/src/libnetworking/pppd/main.c deleted file mode 100644 index 2b4501bfcc..0000000000 --- a/c/src/libnetworking/pppd/main.c +++ /dev/null @@ -1,1284 +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[] = "$Id$"; */ -#endif -*/ -#include -#include -/* #include */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* #include */ -#include "pppd.h" -#include "magic.h" -#include "fsm.h" -#include "lcp.h" -#include "ipcp.h" -#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 - -void SetStatusInfo(int state, char * text, int res); - -/* interface vars */ -char ifname[32]; /* Interface name */ -int interfunit; /* Interface unit number */ - -char *progname; /* Name of this program */ -char hostname[MAXNAMELEN] = "infotel"; /* Our hostname */ -static char default_devnam[MAXPATHLEN]; /* name of default device */ -/*static pid_t pid; */ /* Our pid */ -static uid_t uid; /* Our real user-id */ -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 */ - - - -char *no_ppp_msg = "lack of PPP\n"; - -/* Prototypes for procedures local to this file. */ -static void cleanup(void); -static void create_pidfile __P((void)); -static void close_tty __P((void)); -static void get_input __P((void)); -static void calltimeout __P((void)); -static struct timeval *timeleft __P((struct timeval *)); -static void holdoff_end __P((void *)); -static int device_script __P((char *[], int, int)); -static void reap_kids __P((void)); -static void pr_log __P((void *, char *,...)); - -extern char *ttyname __P((int)); -extern char *getlogin __P((void)); -int main __P((int, char *[])); - - - - - -/* - * 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, - &ccp_protent, -#ifdef IPX_CHANGE - &ipxcp_protent, -#endif -#ifdef AT_CHANGE - &atcp_protent, -#endif - NULL -}; - -extern int connect_stb(); - - -extern int disconnect_stb(); - - -extern struct in_addr rtems_bsdnet_nameserver[]; -extern int rtems_bsdnet_nameserver_count; -extern int __res_init(void); - -int pppdmain(argc, argv) -int argc; -char *argv[]; -{ - int i; - struct timeval timo; - struct protent *protp; - struct stat statbuf; - char t[100]; - - - phase = PHASE_INITIALIZE; - - strcpy(default_devnam, "/dev/modem"); - strcpy(devnam, "/dev/modem"); - - script_env = NULL; - -/* if (gethostname(hostname, MAXNAMELEN) < 0 ) { - die(1); - } - */ - hostname[MAXNAMELEN - 1] = 0; - - uid = 0; - privileged = uid == 0; - - /* - * 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); - - - - if (!ppp_available()) { - 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 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(); - - /* - * Detach ourselves from the terminal, if required, - * and identify who is running us. - */ - -/* - syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d", - VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid); -*/ - - - for (;;) { - -/* !!! here should be done some kind of synchronization - I did it following way ... */ -/* GlobalSystemStatus is set of different things shared between different tasks ... */ -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus * volatile stat; - stat=LockSTBSystemParam(); - stat->ConnectionStatus = NotConnected; - UnlockSTBSystemParam(); -#endif - - - while (1) { - rtems_event_set events; - int status; - -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - status=stat->WantConnection; - UnlockSTBSystemParam(); - - if (status == Connect) break; -#endif - rtems_event_receive(RTEMS_EVENT_1, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); - } -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); -/* stat->WantConnection=DontConnect; */ - stat->ConnectionStatus = Connecting; - -/* Here you can change default nameserver ... */ - rtems_bsdnet_nameserver[0].s_addr=inet_addr(stat->DNS); - rtems_bsdnet_nameserver_count=1; - UnlockSTBSystemParam(); -#endif -/* initialize DNS services here */ - SetStatusInfo(0, "Connecting...",0); - - __res_init(); - /* - * 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; - } - - hungup = 0; - kill_link = 0; - - /* - * Do the equivalent of `mesg n' to stop broadcast messages. - */ - tty_mode = statbuf.st_mode; - - /* run connection script */ - /* - * 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 */ - setdtr(ttyfd, FALSE); - sleep(1); - setdtr(ttyfd, TRUE); - { -/* Make a call ... */ -#if 0 -/* XXX PPPConfiguration */ - char t[100]; - stat=LockSTBSystemParam(); - sprintf(t,"Calling number %s ...",stat->Phone_Number); - UnlockSTBSystemParam(); -#endif - SetStatusInfo(0, t,0); - } - - - if ((i=connect_script(ttyfd)) >0) { -/* here go error messages ... */ - static char *error_msgs[]={ "Bad script", "IO Error" - "Timeout", "Busy", "No dialtone", "No carrier", - "No answer", "No answer from server" }; - setdtr(ttyfd, FALSE); - sprintf(t,"Communication error: %s",error_msgs[i-1]); - syslog(LOG_ERR, "Connect script failed"); - SetStatusInfo(0, t,1); - goto fail; - } - - else - if (i<0) - { - char t[100]; - sprintf(t,"Connecting the Internet at %d baud...",-i); - SetStatusInfo(0, t,0); - } - else - SetStatusInfo(0, "Connecting the Internet...",0); - syslog(LOG_INFO, "Serial connection established."); - - sleep(1); /* give it time to set up its terminal */ - - /* set line speed, flow control, etc.; clear CLOCAL if modem option */ - set_up_tty(ttyfd, 0); - - /* reopen tty if necessary to wait for carrier */ - - /* run welcome script, if any */ -/* if (welcomer && welcomer[0]) { - if (device_script(welcomer, 21, ttyfd) < 0) - syslog(LOG_WARNING, "Welcome script failed"); - } - */ - /* set up the serial device as a ppp interface */ - establish_ppp(ttyfd); - -/* syslog(LOG_INFO, "Using interface ppp%d", interfunit); */ - (void) sprintf(ifname, "ppp%d", interfunit); - - /* - * Start opening the connection and wait for - * incoming events (reply, timeout, etc.). - */ -/* syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); */ - - rtems_bsdnet_semaphore_obtain(); - - lcp_lowerup(0); - lcp_open(0); /* Start protocol */ - - rtems_bsdnet_semaphore_release(); - SetStatusInfo(0, "Internet connection established.",1); - - for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD;) { - wait_input(timeleft(&timo)); - calltimeout(); - get_input(); -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - if (stat->WantConnection==DontConnect) { - stat->ConnectionStatus = NotConnected; - SetStatusInfo(0, "Disconnecting...",0); - lcp_close(0, ""); - kill_link = 0; - } - UnlockSTBSystemParam(); -#endif - 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; - } - } - /* - * 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(); - disestablish_ppp(ttyfd); - SetStatusInfo(0, "Broken internet connection.",1); - - /* - * 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 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - stat->ConnectionStatus = NotConnected; - stat->WantConnection=DontConnect; - UnlockSTBSystemParam(); -#endif - if (ttyfd >= 0) - close_tty(); - - - - } - - return 0; -} - -/* - * detach - detach us from the controlling terminal. - */ -void detach() -{ -} - -/* - * 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) { -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus * volatile stat; -#endif -/* syslog(LOG_NOTICE, "Modem hangup"); */ - hungup = 1; -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - stat->ConnectionStatus = NotConnected; - UnlockSTBSystemParam(); -#endif - - lcp_lowerdown(0); /* serial link is no longer available */ - link_terminated(0); - return; - } -/* if ((debug)) - log_packet(p, len, "rcvd ", LOG_DEBUG); -*/ - - if (len < PPP_HDRLEN) { -/* - if (debug) - MAINDEBUG((LOG_INFO, "io(): Received short packet.")); -*/ - return; - } -/* We need to modify internal network structures here */ - rtems_bsdnet_semaphore_obtain(); - - 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.")); - rtems_bsdnet_semaphore_release(); - 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)) { - - rtems_bsdnet_semaphore_release(); - 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); - rtems_bsdnet_semaphore_release(); - return; - } - if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag - && protp->datainput != NULL) { - (*protp->datainput) (0, p, len); - rtems_bsdnet_semaphore_release(); - return; - } - } - - lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); - rtems_bsdnet_semaphore_release(); -} - - -/* - * 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(); -} - -/* - * cleanup - restore anything which needs to be restored before we exit - */ -/* ARGSUSED */ -static void cleanup() -{ - sys_cleanup(); - - if (ttyfd >= 0) - close_tty(); - -} - -/* - * close_tty - restore the terminal device and close it. - */ -static void close_tty() -{ - disestablish_ppp(ttyfd); - - /* drop dtr to hang up */ - 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); - close(ttyfd); - ttyfd = -1; -} - - -struct callout { - struct timeval c_time; - void *c_arg; - void (*c_func) __P((void *)); - struct callout *c_next; -}; - -static struct callout *callout = NULL; -static struct timeval timenow; - -/* - * timeout - Schedule a timeout. - * - * Note that this timeout takes the number of seconds, NOT hz (as in - * the kernel). - */ -void my_timeout(func, arg, time) -void (*func) __P((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) __P((void *)); -void *arg; -{ - struct callout **copp, *freep; - - MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); - - 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) { - 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; -} - - -/* - * term - Catch SIGTERM signal and SIGINT signal (^C/del). - * - * Indicates that we should initiate a graceful disconnect and exit. - */ -static void term(sig) -int sig; -{ - /* persist = 0; *//* don't try to restart */ - kill_link = 1; -} - -static int input_fd, output_fd; -#include - - - -extern int modem_fd; -int connect_script(int fd) -{ - int status; - char program[256]; -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus * volatile stat; -#endif -/* Connect scripts are almost the same as in Linux Chat ... */ - static char *scripts[] = - { - "TIMEOUT@5@@\rAT@OK-+++\\c-OK@ATH0@TIMEOUT@90@OK@ATDT%s@CONNECT@", - "TIMEOUT@5@@\rAT@OK-+++\\c-OK@ATH0@TIMEOUT@90@OK@ATDT%s@CONNECT@@ppp@@Username:@%s@Password:@%s@" - }; - modem_fd = fd; -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - if (strcmp("",stat->PPP_User)) - { - stat->provider=Poland_TPSA; - } - else - stat->provider=DumbLogin; - switch (stat->provider) { - case Poland_TPSA: /* TPSA - Polish Telecom */ - sprintf(program, scripts[1], stat->Phone_Number, stat->PPP_User, stat->PPP_Password); - break; - default: - sprintf(program, scripts[0], stat->Phone_Number); - - } - UnlockSTBSystemParam(); -#endif - conn_running = 0; - - return chatmain(program); -} - - -/* - * 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; -{ - - return 0; -} - - -/* - * reap_kids - get status from any dead child processes, - * and log a message for abnormal terminations. - */ -static void reap_kids() -{ -} - - -/* - * log_packet - format a packet and log it. - */ - -char line[256]; -char *linep; - -/*#define log_packet(p, len, prefix, level) */ -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. - */ -/*#define format_packet(p, len, printer, arg) */ - -void format_packet(p, len, printer, arg) -u_char *p; -int len; -void (*printer) __P((void *, char *,...)); -void *arg; -{ -/* - int i, n; - u_short proto; - 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. - */ -/*#define print_string(p, len, printer, arg) */ - -void print_string(p, len, printer, arg) -char *p; -int len; -void (*printer) __P((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) -/*#define vfmtmsg(buf, buflen, fmt, args) */ - -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 *); - #ifndef __powerpc__ - n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list)); - #else - - n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *)); - #endif - buf += n; - buflen -= n; - continue; - case 't': - break; - case 'v': - case 'q': - 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; - --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; - */ - return 0; -} - - -/* - * script_setenv - set an environment variable value to be used - * for scripts that we run (e.g. ip-up, auth-up, etc.) - */ -#define script_setenv(var, value) -/* - 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); - - 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; - } - - 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. - */ -#define script_unsetenv(var) -/* - 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/c/src/libnetworking/pppd/options.c b/c/src/libnetworking/pppd/options.c index 759ed988f8..3f56dbf892 100644 --- a/c/src/libnetworking/pppd/options.c +++ b/c/src/libnetworking/pppd/options.c @@ -17,18 +17,15 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" #include #include #include #include -#include -/* #include */ +#include +#include #include -#include #include #include #include @@ -36,6 +33,9 @@ #include #include #include +#ifdef PLUGIN +#include +#endif #ifdef PPP_FILTER #include #include /* XXX: To get struct pcap */ @@ -50,327 +50,1148 @@ #include "upap.h" #include "chap.h" #include "ccp.h" -#ifdef CBCP_SUPPORT -#include "cbcp.h" -#endif - -#ifdef IPX_CHANGE -#include "ipxcp.h" -#endif /* IPX_CHANGE */ #include -#define FALSE 0 -#define TRUE 1 - - -#ifndef GIDSET_TYPE -#define GIDSET_TYPE gid_t -#endif -#if 0 -static int privileged_option; /* set iff the current option came from root */ -static char *option_source; /* string saying where the option came from */ +#if defined(ultrix) || defined(NeXT) +char *strdup __P((char *)); #endif +static const char rcsid[] = RCSID; + /* * Option variables and default values. */ #ifdef PPP_FILTER int dflag = 0; /* Tell libpcap we want debugging */ #endif -int debug = 1; /* Debug flag */ -int kdebugflag = 1; /* Tell kernel to print debug messages */ +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] = "/dev/sccppp"; /* Device name */ +char devnam[MAXPATHLEN]; /* Device name */ int crtscts = 0; /* Use hardware flow control */ -int modem = 0; /* Use modem control lines */ -int inspeed = B115200; /* Input/Output speed requested */ +bool 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[]={"TIMEOUT","3","ABORT","\nBUSY\r","ABORT","\nNO DIALTONE\r","ABORT","\nNO CARRIER\r","ABORT","\nNO ANSWER\r","ABORT","\nRINGING\r\n\r\nRINGING\r", - "","\rAT","OK-+++\\c-OK","ATH0","TIMEOUT","30","OK","ATDT13","CONNECT",""}; -/*char *connector[]={"TIMEOUT","3","ABORT","\nBUSY\r","ABORT","\nNO DIALTONE\r","ABORT","\nNO CARRIER\r","ABORT","\nNO ANSWER\r","ABORT","\nRINGING\r\n\r\nRINGING\r", - "","\rAT","OK-+++\\c-OK","ATH0","TIMEOUT","30","OK","ATDT0202122","CONNECT","","ppp","","Username:","ppp","Password:","ppp"}; -*/ -char **disconnector; /* Script to disestablish physical link */ -char **welcomer; /* Script to run after phys link estab. */ +bool lockflag = 0; /* Create lock file to lock the serial dev */ +bool nodetach = 0; /* Don't detach from controlling tty */ +bool updetach = 0; /* Detach once link is up */ +char *initializer = NULL; /* Script to initialize physical link */ +char *connect_script = NULL; /* Script to establish physical link */ +char *disconnect_script = NULL; /* Script to disestablish physical link */ +char *welcomer = NULL; /* Script to run after phys link estab. */ +char *ptycommand = NULL; /* Command to run on other side of pty */ int maxconnect = 0; /* Maximum connect time */ -char user[MAXNAMELEN]="stb"; /* Username for PAP */ -char passwd[MAXSECRETLEN]="stb"; /* Password for PAP */ -int auth_required = 0; /* Peer is required to authenticate */ -int defaultroute = 1; /* assign default route through interface */ -int proxyarp = 0; /* Set up proxy ARP entry for peer */ -int persist = 1; /* 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]="infotel"; /* 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 = 1; /* Don't use hostname for default IP adrs */ -int demand = 0; /* do dial-on-demand */ +char user[MAXNAMELEN]; /* Username for PAP */ +char passwd[MAXSECRETLEN]; /* Password for PAP */ +bool persist = 0; /* Reopen link after it goes down */ +char our_name[MAXNAMELEN]; /* Our name for authentication purposes */ +bool 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 = 1; /* Set to say we won't do CHAP */ +bool holdoff_specified; /* true if a holdoff value has been given */ +bool notty = 0; /* Stdin/out is not a tty */ +char *record_file = NULL; /* File to record chars sent/received */ +int using_pty = 0; +bool sync_serial = 0; /* Device is synchronous serial device */ +int log_to_fd = 1; /* send log messages to this fd too */ +int maxfail = 10; /* max # of unsuccessful connection attempts */ +char linkname[MAXPATHLEN]; /* logical name for link */ +bool tune_kernel; /* may alter kernel settings */ +int connect_delay = 1000; /* wait this many ms after connect script */ -#ifdef MSLANMAN -int ms_lanman = 0; /* Nonzero if use LanMan password instead of NT */ - /* Has meaning only with MS-CHAP challenges */ -#endif +extern option_t auth_options[]; +extern struct stat devstat; +extern int prepass; /* Doing pre-pass to find device name */ -struct option_info auth_req_info; -struct option_info connector_info; -struct option_info disconnector_info; +struct option_info initializer_info; +struct option_info connect_script_info; +struct option_info disconnect_script_info; struct option_info welcomer_info; struct option_info devnam_info; +struct option_info ptycommand_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 +char *current_option; /* the name of the option being parsed */ +int privileged_option; /* set iff the current option came from root */ +char *option_source; /* string saying where the option came from */ +bool log_to_file; /* log_to_fd is a file opened by us */ + /* * Prototypes */ -#if 0 -static int setdevname __P((char *, int)); +static int setdevname __P((char *)); static int setipaddr __P((char *)); static int setspeed __P((char *)); -static int setdebug __P((char **)); -static int setkdebug __P((char **)); -static int setpassive __P((char **)); -static int setsilent __P((char **)); static int noopt __P((char **)); -static int setnovj __P((char **)); -static int setnovjccomp __P((char **)); -static int setvjslots __P((char **)); -static int reqpap __P((char **)); -static int nopap __P((char **)); -#ifdef OLD_OPTIONS -static int setupapfile __P((char **)); -#endif -static int nochap __P((char **)); -static int reqchap __P((char **)); -static int noaccomp __P((char **)); -static int noasyncmap __P((char **)); -static int noip __P((char **)); -static int nomagicnumber __P((char **)); -static int setasyncmap __P((char **)); -static int setescape __P((char **)); -static int setmru __P((char **)); -static int setmtu __P((char **)); -#ifdef CBCP_SUPPORT -static int setcbcp __P((char **)); -#endif -static int nomru __P((char **)); -static int nopcomp __P((char **)); -static int setconnector __P((char **)); -static int setdisconnector __P((char **)); -static int setwelcomer __P((char **)); -static int setmaxconnect __P((char **)); static int setdomain __P((char **)); static int setnetmask __P((char **)); -static int setcrtscts __P((char **)); -static int setnocrtscts __P((char **)); static int setxonxoff __P((char **)); -static int setnodetach __P((char **)); -static int setupdetach __P((char **)); -static int setmodem __P((char **)); -static int setlocal __P((char **)); -static int setlock __P((char **)); -static int setname __P((char **)); -static int setuser __P((char **)); -static int setremote __P((char **)); -static int setauth __P((char **)); -static int setnoauth __P((char **)); static int readfile __P((char **)); static int callfile __P((char **)); -static int setdefaultroute __P((char **)); -static int setnodefaultroute __P((char **)); -static int setproxyarp __P((char **)); -static int setnoproxyarp __P((char **)); -static int setpersist __P((char **)); -static int setnopersist __P((char **)); -static int setdologin __P((char **)); -static int setusehostname __P((char **)); -static int setnoipdflt __P((char **)); -static int setlcptimeout __P((char **)); -static int setlcpterm __P((char **)); -static int setlcpconf __P((char **)); -static int setlcpfails __P((char **)); -static int setipcptimeout __P((char **)); -static int setipcpterm __P((char **)); -static int setipcpconf __P((char **)); -static int setipcpfails __P((char **)); -static int setpaptimeout __P((char **)); -static int setpapreqs __P((char **)); -static int setpapreqtime __P((char **)); -static int setchaptimeout __P((char **)); -static int setchapchal __P((char **)); -static int setchapintv __P((char **)); -static int setipcpaccl __P((char **)); -static int setipcpaccr __P((char **)); -static int setlcpechointv __P((char **)); -static int setlcpechofails __P((char **)); -static int noccp __P((char **)); -static int setbsdcomp __P((char **)); -static int setnobsdcomp __P((char **)); -static int setdeflate __P((char **)); -static int setnodeflate __P((char **)); -static int setnodeflatedraft __P((char **)); -static int setdemand __P((char **)); -static int setpred1comp __P((char **)); -static int setnopred1comp __P((char **)); -static int setipparam __P((char **)); -static int setpapcrypt __P((char **)); -static int setidle __P((char **)); -static int setholdoff __P((char **)); -static int setdnsaddr __P((char **)); -static int resetipxproto __P((char **)); -static int setwinsaddr __P((char **)); -static int showversion __P((char **)); -static int showhelp __P((char **)); +static void usage __P((void)); +static int setlogfile __P((char **)); +#ifdef PLUGIN +static int loadplugin __P((char **)); +#endif #ifdef PPP_FILTER -static int setpdebug __P((char **)); static int setpassfilter __P((char **)); static int setactivefilter __P((char **)); #endif -#ifdef IPX_CHANGE -static int setipxproto __P((char **)); -static int setipxanet __P((char **)); -static int setipxalcl __P((char **)); -static int setipxarmt __P((char **)); -static int setipxnetwork __P((char **)); -static int setipxnode __P((char **)); -static int setipxrouter __P((char **)); -static int setipxname __P((char **)); -static int setipxcptimeout __P((char **)); -static int setipxcpterm __P((char **)); -static int setipxcpconf __P((char **)); -static int setipxcpfails __P((char **)); -#endif /* IPX_CHANGE */ - -#ifdef MSLANMAN -static int setmslanman __P((char **)); -#endif - +static option_t *find_option __P((char *name)); +static int process_option __P((option_t *, char **)); +static int n_arguments __P((option_t *)); static int number_option __P((char *, u_int32_t *, int)); -static int int_option __P((char *, int *)); -static int readable __P((int fd)); -#endif + +/* + * Structure to store extra lists of options. + */ +struct option_list { + option_t *options; + struct option_list *next; +}; + +static struct option_list *extra_options = NULL; /* * Valid arguments. */ - +option_t general_options[] = { + { "debug", o_int, &debug, + "Increase debugging level", OPT_INC|OPT_NOARG|1 }, + { "-d", o_int, &debug, + "Increase debugging level", OPT_INC|OPT_NOARG|1 }, + { "kdebug", o_int, &kdebugflag, + "Set kernel driver debug level" }, + { "nodetach", o_bool, &nodetach, + "Don't detach from controlling tty", 1 }, + { "-detach", o_bool, &nodetach, + "Don't detach from controlling tty", 1 }, + { "updetach", o_bool, &updetach, + "Detach from controlling tty once link is up", 1 }, + { "holdoff", o_int, &holdoff, + "Set time in seconds before retrying connection" }, + { "idle", o_int, &idle_time_limit, + "Set time in seconds before disconnecting idle link" }, + { "lock", o_bool, &lockflag, + "Lock serial device with UUCP-style lock file", 1 }, + { "-all", o_special_noarg, noopt, + "Don't request/allow any LCP or IPCP options (useless)" }, + { "init", o_string, &initializer, + "A program to initialize the device", + OPT_A2INFO | OPT_PRIVFIX, &initializer_info }, + { "connect", o_string, &connect_script, + "A program to set up a connection", + OPT_A2INFO | OPT_PRIVFIX, &connect_script_info }, + { "disconnect", o_string, &disconnect_script, + "Program to disconnect serial device", + OPT_A2INFO | OPT_PRIVFIX, &disconnect_script_info }, + { "welcome", o_string, &welcomer, + "Script to welcome client", + OPT_A2INFO | OPT_PRIVFIX, &welcomer_info }, + { "pty", o_string, &ptycommand, + "Script to run on pseudo-tty master side", + OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info }, + { "notty", o_bool, ¬ty, + "Input/output is not a tty", OPT_DEVNAM | 1 }, + { "record", o_string, &record_file, + "Record characters sent/received to file" }, + { "maxconnect", o_int, &maxconnect, + "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF }, + { "crtscts", o_int, &crtscts, + "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) }, + { "nocrtscts", o_int, &crtscts, + "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, + { "-crtscts", o_int, &crtscts, + "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, + { "cdtrcts", o_int, &crtscts, + "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) }, + { "nocdtrcts", o_int, &crtscts, + "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, + { "xonxoff", o_special_noarg, setxonxoff, + "Set software (XON/XOFF) flow control" }, + { "domain", o_special, setdomain, + "Add given domain name to hostname" }, + { "mtu", o_int, &lcp_allowoptions[0].mru, + "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, + { "netmask", o_special, setnetmask, + "set netmask" }, + { "modem", o_bool, &modem, + "Use modem control lines", 1 }, + { "local", o_bool, &modem, + "Don't use modem control lines" }, + { "file", o_special, readfile, + "Take options from a file", OPT_PREPASS }, + { "call", o_special, callfile, + "Take options from a privileged file", OPT_PREPASS }, + { "persist", o_bool, &persist, + "Keep on reopening connection after close", 1 }, + { "nopersist", o_bool, &persist, + "Turn off persist option" }, + { "demand", o_bool, &demand, + "Dial on demand", OPT_INITONLY | 1, &persist }, + { "sync", o_bool, &sync_serial, + "Use synchronous HDLC serial encoding", 1 }, + { "logfd", o_int, &log_to_fd, + "Send log messages to this file descriptor" }, + { "logfile", o_special, setlogfile, + "Append log messages to this file" }, + { "nolog", o_int, &log_to_fd, + "Don't send log messages to any file", + OPT_NOARG | OPT_VAL(-1) }, + { "nologfd", o_int, &log_to_fd, + "Don't send log messages to any file descriptor", + OPT_NOARG | OPT_VAL(-1) }, + { "linkname", o_string, linkname, + "Set logical name for link", + OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, + { "maxfail", o_int, &maxfail, + "Maximum number of unsuccessful connection attempts to allow" }, + { "ktune", o_bool, &tune_kernel, + "Alter kernel settings as necessary", 1 }, + { "noktune", o_bool, &tune_kernel, + "Don't alter kernel settings", 0 }, + { "connect-delay", o_int, &connect_delay, + "Maximum time (in ms) to wait after connect script finishes" }, +#ifdef PLUGIN + { "plugin", o_special, loadplugin, + "Load a plug-in module into pppd", OPT_PRIV }, +#endif + +#ifdef PPP_FILTER + { "pdebug", o_int, &dflag, + "libpcap debugging" }, + { "pass-filter", 1, setpassfilter, + "set filter for packets to pass" }, + { "active-filter", 1, setactivefilter, + "set filter for active pkts" }, +#endif + + { NULL } +}; + +#ifndef IMPLEMENTATION +#define IMPLEMENTATION "" +#endif + +static char *usage_string = "\ +pppd version %s.%d%s\n\ +Usage: %s [ options ], where options are:\n\ + Communicate over the named device\n\ + Set the baud rate to \n\ + : Set the local and/or remote interface IP\n\ + addresses. Either one may be omitted.\n\ + asyncmap Set the desired async map to hex \n\ + auth Require authentication from peer\n\ + connect

Invoke shell command

to set up the serial line\n\ + crtscts Use hardware RTS/CTS flow control\n\ + defaultroute Add default route through interface\n\ + file Take options from file \n\ + modem Use modem control lines\n\ + mru Set MRU value to for negotiation\n\ +See pppd(8) for more options.\n\ +"; + /* * parse_args - parse a string of arguments from the command line. + * If prepass is true, we are scanning for the device name and only + * processing a few options, so error messages are suppressed. */ int parse_args(argc, argv) int argc; char **argv; { + char *arg; + option_t *opt; + int ret; + + privileged_option = privileged; + option_source = "command line"; + while (argc > 0) { + arg = *argv++; + --argc; + /* + * First see if it's an option in the new option list. + */ + opt = find_option(arg); + if (opt != NULL) { + int n = n_arguments(opt); + if (argc < n) { + option_error("too few parameters for option %s", arg); + return 0; + } + current_option = arg; + if (!process_option(opt, argv)) + return 0; + argc -= n; + argv += n; + continue; + } -return 0; + /* + * Maybe a tty name, speed or IP address? + */ + if ((ret = setdevname(arg)) == 0 + && (ret = setspeed(arg)) == 0 + && (ret = setipaddr(arg)) == 0 + && !prepass) { + option_error("unrecognized option '%s'", arg); + usage(); + return 0; + } + if (ret < 0) /* error */ + return 0; + } + return 1; } +#if 0 /* * scan_args - scan the command line arguments to get the tty name, - * if specified. + * if specified. Also checks whether the notty or pty option was given. */ +void +scan_args(argc, argv) + int argc; + char **argv; +{ + char *arg; + option_t *opt; + + privileged_option = privileged; + while (argc > 0) { + arg = *argv++; + --argc; + + if (strcmp(arg, "notty") == 0 || strcmp(arg, "pty") == 0) + using_pty = 1; + + /* Skip options and their arguments */ + opt = find_option(arg); + if (opt != NULL) { + int n = n_arguments(opt); + argc -= n; + argv += n; + continue; + } + + /* Check if it's a tty name and copy it if so */ + (void) setdevname(arg, 1); + } +} +#endif /* - * usage - print out a message telling how to use the program. + * options_from_file - Read a string of options from a file, + * and interpret them. */ -void -usage() +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, err; + option_t *opt; + int oldpriv; + char *oldsource; + char *argv[MAXARGS]; + char args[MAXARGS][MAXWORDLEN]; + char cmd[MAXWORDLEN]; + + f = fopen(filename, "r"); + err = errno; + if (f == NULL) { + if (!must_exist && err == ENOENT) + return 1; + errno = err; + option_error("Can't open options file %s: %m", filename); + return 0; + } + + oldpriv = privileged_option; + privileged_option = priv; + oldsource = option_source; + option_source = strdup(filename); + if (option_source == NULL) + option_source = "file"; + ret = 0; + while (getword(f, cmd, &newline, filename)) { + /* + * First see if it's a command. + */ + opt = find_option(cmd); + if (opt != NULL) { + int n = n_arguments(opt); + for (i = 0; i < n; ++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 ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) { + option_error("the %s option may not be used in the %s file", + cmd, filename); + goto err; + } + if (!process_option(opt, argv)) + goto err; + continue; + } + + /* + * Maybe a tty name, speed or IP address? + */ + if ((i = setdevname(cmd)) == 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; + option_source = oldsource; + return ret; +} /* - * showhelp - print out usage message and exit. + * options_from_user - See if the use has a ~/.ppprc file, + * and if so, interpret options from it. */ -static int -showhelp(argv) - char **argv; +int +options_from_user() { return 0; } /* - * showversion - print out the version number and exit. + * 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; + size_t pl; + + dev = devnam; + if (strncmp(dev, "/dev/", 5) == 0) + dev += 5; + if (dev[0] == 0 || strcmp(dev, "tty") == 0) + return 1; /* don't look for /etc/ppp/options.tty */ + pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1; + path = malloc(pl); + if (path == NULL) + novm("tty init file name"); + slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev); + /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */ + for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p) + if (*p == '/') + *p = '.'; + ret = options_from_file(path, 0, 0, 1); + free(path); + return ret; +} + +/* + * options_from_list - process a string of options in a wordlist. + */ +int +options_from_list(w, priv) + struct wordlist *w; + int priv; +{ + char *argv[MAXARGS]; + option_t *opt; + int i, ret = 0; + + privileged_option = priv; + option_source = "secrets file"; + + while (w != NULL) { + /* + * First see if it's a command. + */ + opt = find_option(w->word); + if (opt != NULL) { + int n = n_arguments(opt); + struct wordlist *w0 = w; + for (i = 0; i < n; ++i) { + w = w->next; + if (w == NULL) { + option_error( + "In secrets file: too few parameters for option '%s'", + w0->word); + goto err; + } + argv[i] = w->word; + } + current_option = w0->word; + if (!process_option(opt, argv)) + goto err; + w = w->next; + continue; + } + + /* + * Maybe a tty name, speed or IP address? + */ + if ((i = setdevname(w->word)) == 0 + && (i = setspeed(w->word)) == 0 + && (i = setipaddr(w->word)) == 0) { + option_error("In secrets file: unrecognized option '%s'", + w->word); + goto err; + } + if (i < 0) /* error */ + goto err; + w = w->next; + } + ret = 1; + +err: + return ret; +} + +/* + * find_option - scan the option lists for the various protocols + * looking for an entry with the given name. + * This could be optimized by using a hash table. + */ +static option_t * +find_option(name) + char *name; +{ + option_t *opt; + struct option_list *list; + int i; + + for (list = extra_options; list != NULL; list = list->next) + for (opt = list->options; opt->name != NULL; ++opt) + if (strcmp(name, opt->name) == 0) + return opt; + for (opt = general_options; opt->name != NULL; ++opt) + if (strcmp(name, opt->name) == 0) + return opt; + for (opt = auth_options; opt->name != NULL; ++opt) + if (strcmp(name, opt->name) == 0) + return opt; + for (i = 0; protocols[i] != NULL; ++i) + if ((opt = protocols[i]->options) != NULL) + for (; opt->name != NULL; ++opt) + if (strcmp(name, opt->name) == 0) + return opt; + return NULL; +} + +/* + * process_option - process one new-style option. */ static int -showversion(argv) +process_option(opt, argv) + option_t *opt; char **argv; { - return 0; + u_int32_t v; + int iv, a; + char *sv; + int (*parser) __P((char **)); + + if ((opt->flags & OPT_PREPASS) == 0 && prepass) + return 1; + if ((opt->flags & OPT_INITONLY) && phase != PHASE_INITIALIZE) { + option_error("it's too late to use the %s option", opt->name); + return 0; + } + if ((opt->flags & OPT_PRIV) && !privileged_option) { + option_error("using the %s option requires root privilege", opt->name); + return 0; + } + if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) { + option_error("%s option is disabled", opt->name); + return 0; + } + if ((opt->flags & OPT_PRIVFIX) && !privileged_option) { + struct option_info *ip = (struct option_info *) opt->addr2; + if (ip && ip->priv) { + option_error("%s option cannot be overridden", opt->name); + return 0; + } + } + + switch (opt->type) { + case o_bool: + v = opt->flags & OPT_VALUE; + *(bool *)(opt->addr) = v; + if (opt->addr2 && (opt->flags & OPT_A2COPY)) + *(bool *)(opt->addr2) = v; + break; + + case o_int: + iv = 0; + if ((opt->flags & OPT_NOARG) == 0) { + if (!int_option(*argv, &iv)) + return 0; + if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit) + || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit)) + && !((opt->flags & OPT_ZEROOK && iv == 0))) { + char *zok = (opt->flags & OPT_ZEROOK)? " zero or": ""; + switch (opt->flags & OPT_LIMITS) { + case OPT_LLIMIT: + option_error("%s value must be%s >= %d", + opt->name, zok, opt->lower_limit); + break; + case OPT_ULIMIT: + option_error("%s value must be%s <= %d", + opt->name, zok, opt->upper_limit); + break; + case OPT_LIMITS: + option_error("%s value must be%s between %d and %d", + opt->name, opt->lower_limit, opt->upper_limit); + break; + } + return 0; + } + } + a = opt->flags & OPT_VALUE; + if (a >= 128) + a -= 256; /* sign extend */ + iv += a; + if (opt->flags & OPT_INC) + iv += *(int *)(opt->addr); + if ((opt->flags & OPT_NOINCR) && !privileged_option) { + int oldv = *(int *)(opt->addr); + if ((opt->flags & OPT_ZEROINF) ? + (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) { + option_error("%s value cannot be increased", opt->name); + return 0; + } + } + *(int *)(opt->addr) = iv; + if (opt->addr2 && (opt->flags & OPT_A2COPY)) + *(int *)(opt->addr2) = iv; + break; + + case o_uint32: + if (opt->flags & OPT_NOARG) { + v = opt->flags & OPT_VALUE; + } else if (!number_option(*argv, &v, 16)) + return 0; + if (opt->flags & OPT_OR) + v |= *(u_int32_t *)(opt->addr); + *(u_int32_t *)(opt->addr) = v; + if (opt->addr2 && (opt->flags & OPT_A2COPY)) + *(u_int32_t *)(opt->addr2) = v; + break; + + case o_string: + if (opt->flags & OPT_STATIC) { + strlcpy((char *)(opt->addr), *argv, opt->upper_limit); + } else { + sv = strdup(*argv); + if (sv == NULL) + novm("option argument"); + *(char **)(opt->addr) = sv; + } + break; + + case o_special_noarg: + case o_special: + parser = (int (*) __P((char **))) opt->addr; + if (!(*parser)(argv)) + return 0; + break; + } + + if (opt->addr2) { + if (opt->flags & OPT_A2INFO) { + struct option_info *ip = (struct option_info *) opt->addr2; + ip->priv = privileged_option; + ip->source = option_source; + } else if ((opt->flags & (OPT_A2COPY|OPT_ENABLE)) == 0) + *(bool *)(opt->addr2) = 1; + } + + return 1; +} + +/* + * n_arguments - tell how many arguments an option takes + */ +static int +n_arguments(opt) + option_t *opt; +{ + return (opt->type == o_bool || opt->type == o_special_noarg + || (opt->flags & OPT_NOARG))? 0: 1; } +/* + * add_options - add a list of options to the set we grok. + */ void -option_error __V((char *fmt, ...)) +add_options(opt) + option_t *opt; +{ + struct option_list *list; + + list = malloc(sizeof(*list)); + if (list == 0) + novm("option list entry"); + list->options = opt; + list->next = extra_options; + extra_options = list; +} + +/* + * usage - print out a message telling how to use the program. + */ +static void +usage() { + if (phase == PHASE_INITIALIZE) + fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION, + progname); } + /* - * readable - check if a file is readable by the real user. + * option_error - print a message about an error in an option. + * The message is logged, and also sent to + * stderr if phase == PHASE_INITIALIZE. */ -/*static int -readable(fd) - int fd; +void +option_error __V((char *fmt, ...)) { - uid_t uid; - int ngroups, i; - struct stat sbuf; - GIDSET_TYPE groups[NGROUPS_MAX]; + va_list args; + char buf[256]; - 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; +#if defined(__STDC__) + va_start(args, fmt); +#else + char *fmt; + va_start(args); + fmt = va_arg(args, char *); +#endif + if (prepass) { + va_end(args); + return; + } + vslprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + fprintf(stderr, "pppd: %s\n", buf); } -*/ + /* * Read a word from a file. * Words are delimited by white-space or by quotes (" or '). * Quotes, white-space and \ may be escaped with \. * \ 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 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. + */ +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 may not contain /../, start with / or ../, or end in /.. */ - /* - * setdebug - Set debug (command line argument). +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"); + slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg); + + ok = options_from_file(fname, 1, 1, 1); + + free(fname); + return ok; +} + +#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. @@ -384,10 +1205,317 @@ noopt(argv) 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); +} + +/* + * 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); +} + + +/* + * setspeed - Set the speed. + */ +static int +setspeed(arg) + char *arg; +{ + int spd; + int ret = (int )1; + speed_t spdValue = (speed_t)0; + char *ptr; + + if ( !prepass ) { + spd = strtol(arg, &ptr, 0); + if (ptr == arg || *ptr != 0 || spd == 0) { + ret = (int)0; + } + else { + switch ( spd ) { + case 2400: + spdValue = B2400; + break; + case 4800: + spdValue = B4800; + break; + case 9600: + spdValue = B9600; + break; + case 19200: + spdValue = B19200; + break; + case 38400: + spdValue = B38400; + break; + case 57600: + spdValue = B57600; + break; + case 115200: + spdValue = B115200; + break; + default: + ret = (int)0; + break; + } + + if ( spdValue ) { + inspeed = spdValue; + } + } + } + + return ( ret ); +} + + +/* + * setdevname - Set the device name. + */ +static int +setdevname(cp) + char *cp; +{ + struct stat statbuf; + char dev[MAXPATHLEN]; + + if (*cp == 0) + return 0; + + if (strncmp("/dev/", cp, 5) != 0) { + strlcpy(dev, "/dev/", sizeof(dev)); + strlcat(dev, cp, sizeof(dev)); + cp = dev; + } + + /* + * Check if there is a character device by this name. + */ + if (stat(cp, &statbuf) < 0) { + if (errno == ENOENT) + return 0; + option_error("Couldn't stat %s: %m", cp); + return -1; + } + if (!S_ISCHR(statbuf.st_mode)) { + option_error("%s is not a character device", cp); + return -1; + } + + if (phase != PHASE_INITIALIZE) { + option_error("device name cannot be changed after initialization"); + return -1; + } else if (devnam_fixed) { + option_error("per-tty options file may not specify device name"); + return -1; + } + + if (devnam_info.priv && !privileged_option) { + option_error("device name cannot be overridden"); + return -1; + } + + strlcpy(devnam, cp, sizeof(devnam)); + devstat = statbuf; + default_device = 0; + devnam_info.priv = privileged_option; + devnam_info.source = option_source; + + return 1; +} + + +/* + * setipaddr - Set the IP address + */ +static 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 (prepass) + return 1; + + /* + * If colon first character, then no local addr. + */ + if (colon != arg) { + *colon = '\0'; + if ((local = inet_addr(arg)) == (u_int32_t) -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)) == (u_int32_t) -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) + strlcpy(remote_name, colon, sizeof(remote_name)); + } + } + 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; +} + + +/* + * setnetmask - set the netmask to be used on the interface. + */ +static int +setnetmask(argv) + char **argv; +{ + u_int32_t mask, b; + int n, ok; + char *p, *endp; + + /* + * Unfortunately, if we use inet_addr, we can't tell whether + * a result of all 1s is an error or a valid 255.255.255.255. + */ + p = *argv; + ok = 0; + mask = 0; + for (n = 3;; --n) { + b = strtoul(p, &endp, 0); + if (endp == p) + break; + if (b > 255) { + if (n == 3) { + /* accept e.g. 0xffffff00 */ + p = endp; + mask = b; + } + break; + } + mask |= b << (n * 8); + p = endp; + if (*p != '.' || n == 0) + break; + ++p; + } + + mask = htonl(mask); + + if (*p != 0 || (netmask & ~mask) != 0) { + option_error("invalid netmask value '%s'", *argv); + return 0; + } + + netmask = mask; + 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 +setlogfile(argv) + char **argv; +{ + int fd, err; + + fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644); + if (fd < 0 && errno == EEXIST) + fd = open(*argv, O_WRONLY | O_APPEND); + err = errno; + if (fd < 0) { + errno = err; + option_error("Can't open log file %s: %m", *argv); + return 0; + } + if (log_to_file && log_to_fd >= 0) + close(log_to_fd); + log_to_fd = fd; + log_to_file = 1; + return 1; +} + +#ifdef PLUGIN +static int +loadplugin(argv) + char **argv; +{ + char *arg = *argv; + void *handle; + const char *err; + void (*init) __P((void)); + + handle = dlopen(arg, RTLD_GLOBAL | RTLD_NOW); + if (handle == 0) { + err = dlerror(); + if (err != 0) + option_error("%s", err); + option_error("Couldn't load plugin %s", arg); + return 0; + } + init = dlsym(handle, "plugin_init"); + if (init == 0) { + option_error("%s has no initialization entry point", arg); + dlclose(handle); + return 0; + } + info("Plugin %s loaded.", arg); + (*init)(); + return 1; +} +#endif /* PLUGIN */ diff --git a/c/src/libnetworking/pppd/patchlevel.h b/c/src/libnetworking/pppd/patchlevel.h index 02bf115c52..54d88b8a66 100644 --- a/c/src/libnetworking/pppd/patchlevel.h +++ b/c/src/libnetworking/pppd/patchlevel.h @@ -1,6 +1,6 @@ /* $Id$ */ -#define PATCHLEVEL 5 +#define PATCHLEVEL 11 #define VERSION "2.3" #define IMPLEMENTATION "" -#define DATE "4 May 1998" +#define DATE "23 December 1999" diff --git a/c/src/libnetworking/pppd/pathnames.h b/c/src/libnetworking/pppd/pathnames.h index b954204f5c..0a4f6e69f2 100644 --- a/c/src/libnetworking/pppd/pathnames.h +++ b/c/src/libnetworking/pppd/pathnames.h @@ -8,23 +8,36 @@ #include #else +#ifndef _PATH_VARRUN #define _PATH_VARRUN "/etc/ppp/" +#endif #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 "/etc/ppp/connect-errors" -#define _PATH_USEROPT ".ppprc" -#define _PATH_PEERFILES "/etc/ppp/peers/" +#ifndef _ROOT_PATH +#define _ROOT_PATH +#endif + +#define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets" +#define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets" +#define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options" +#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up" +#define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down" +#define _PATH_AUTHUP _ROOT_PATH "/etc/ppp/auth-up" +#define _PATH_AUTHDOWN _ROOT_PATH "/etc/ppp/auth-down" +#define _PATH_TTYOPT _ROOT_PATH "/etc/ppp/options." +#define _PATH_CONNERRS _ROOT_PATH "/etc/ppp/connect-errors" +#define _PATH_PEERFILES _ROOT_PATH "/etc/ppp/peers/" +#define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf" + +#define _PATH_USEROPT ".ppprc" + +#ifdef INET6 +#define _PATH_IPV6UP _ROOT_PATH "/etc/ppp/ipv6-up" +#define _PATH_IPV6DOWN _ROOT_PATH "/etc/ppp/ipv6-down" +#endif #ifdef IPX_CHANGE -#define _PATH_IPXUP "/etc/ppp/ipx-up" -#define _PATH_IPXDOWN "/etc/ppp/ipx-down" +#define _PATH_IPXUP _ROOT_PATH "/etc/ppp/ipx-up" +#define _PATH_IPXDOWN _ROOT_PATH "/etc/ppp/ipx-down" #endif /* IPX_CHANGE */ diff --git a/c/src/libnetworking/pppd/ppp_tty.c b/c/src/libnetworking/pppd/ppp_tty.c deleted file mode 100644 index fccdd3a8ab..0000000000 --- a/c/src/libnetworking/pppd/ppp_tty.c +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous - * tty devices. - * - * 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. - * - * Drew D. Perkins - * Carnegie Mellon University - * 4910 Forbes Ave. - * Pittsburgh, PA 15213 - * (412) 268-8576 - * ddp@andrew.cmu.edu - * - * Based on: - * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89 - * - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Serial Line interface - * - * Rick Adams - * Center for Seismic Studies - * 1300 N 17th Street, Suite 1450 - * Arlington, Virginia 22209 - * (703)276-7900 - * rick@seismo.ARPA - * seismo!rick - * - * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). - * Converted to 4.3BSD Beta by Chris Torek. - * Other changes made at Berkeley, based in part on code by Kirk Smith. - * - * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com) - * Added VJ tcp header compression; more unified ioctls - * - * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au). - * Cleaned up a lot of the mbuf-related code to fix bugs that - * caused system crashes and packet corruption. Changed pppstart - * so that it doesn't just give up with a "collision" if the whole - * packet doesn't fit in the output ring buffer. - * - * Added priority queueing for interactive IP packets, following - * the model of if_sl.c, plus hooks for bpf. - * Paul Mackerras (paulus@cs.anu.edu.au). - */ - -/* $Id$ */ -/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ -/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */ - -#include "ppp.h" -#if NPPP > 0 - -#define VJC -#define PPP_COMPRESS - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef VJC -#include -#include -#include -#include -#endif - -#ifdef PPP_FILTER -#include -#endif -#include -#include -#include - -void pppasyncattach __P((void)); -int pppopen __P((dev_t dev, struct tty *tp)); -int pppclose __P((struct tty *tp, int flag)); -int pppread __P((struct tty *tp, struct uio *uio, int flag)); -int pppwrite __P((struct tty *tp, struct uio *uio, int flag)); -int ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag, - struct proc *)); -int pppinput __P((int c, struct tty *tp)); -int pppstart __P((struct tty *tp)); - -static u_short pppfcs __P((u_short fcs, u_char *cp, int len)); -static void pppasyncstart __P((struct ppp_softc *)); -static void pppasyncctlp __P((struct ppp_softc *)); -static void pppasyncrelinq __P((struct ppp_softc *)); -static void ppp_timeout __P((void *)); -static void pppgetm __P((struct ppp_softc *sc)); -static void pppdumpb __P((u_char *b, int l)); -static void ppplogchar __P((struct ppp_softc *, int)); - -/* - * Some useful mbuf macros not in mbuf.h. - */ -#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT) - -#define M_DATASTART(m) \ - (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \ - (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat) - -#define M_DATASIZE(m) \ - (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \ - (m)->m_flags & M_PKTHDR ? MHLEN: MLEN) - -/* - * Does c need to be escaped? - */ -#define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F))) - -/* - * Procedures for using an async tty interface for PPP. - */ - -/* This is a FreeBSD-2.0 kernel. */ -#define CCOUNT(q) ((q)->c_cc) -#define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */ -#define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */ - -/* - * Define the PPP line discipline. - */ - -static struct linesw pppdisc = { - pppopen, pppclose, pppread, pppwrite, ppptioctl, - pppinput, pppstart, ttymodem -}; - -void -pppasyncattach() -{ - linesw[PPPDISC] = pppdisc; -} - -TEXT_SET(pseudo_set, pppasyncattach); - -/* - * Line specific open routine for async tty devices. - * Attach the given tty to the first available ppp unit. - * Called from device open routine or ttioctl. - */ -/* ARGSUSED */ -int -pppopen(dev, tp) - dev_t dev; - register struct tty *tp; -{ - struct proc *p = curproc; /* XXX */ - register struct ppp_softc *sc; - int error, s; - - if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) - return (error); - - s = spltty(); - - if (tp->t_line == PPPDISC) { - sc = (struct ppp_softc *) tp->t_sc; - if (sc != NULL && sc->sc_devp == (void *) tp) { - splx(s); - return (0); - } - } - - if ((sc = pppalloc(p->p_pid)) == NULL) { - splx(s); - return ENXIO; - } - - if (sc->sc_relinq) - (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */ - - sc->sc_ilen = 0; - sc->sc_m = NULL; - bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); - sc->sc_asyncmap[0] = 0xffffffff; - sc->sc_asyncmap[3] = 0x60000000; - sc->sc_rasyncmap = 0; - sc->sc_devp = (void *) tp; - sc->sc_start = pppasyncstart; - sc->sc_ctlp = pppasyncctlp; - sc->sc_relinq = pppasyncrelinq; - sc->sc_outm = NULL; - pppgetm(sc); - sc->sc_if.if_flags |= IFF_RUNNING; - sc->sc_if.if_baudrate = tp->t_ospeed; - - tp->t_sc = (caddr_t) sc; - ttyflush(tp, FREAD | FWRITE); - - splx(s); - return (0); -} - -/* - * Line specific close routine, called from device close routine - * and from ttioctl. - * Detach the tty from the ppp unit. - * Mimics part of ttyclose(). - */ -int -pppclose(tp, flag) - struct tty *tp; - int flag; -{ - register struct ppp_softc *sc; - int s; - - s = spltty(); - ttyflush(tp, FREAD|FWRITE); - tp->t_line = 0; - sc = (struct ppp_softc *) tp->t_sc; - if (sc != NULL) { - tp->t_sc = NULL; - if (tp == (struct tty *) sc->sc_devp) { - pppasyncrelinq(sc); - pppdealloc(sc); - } - } - splx(s); - return 0; -} - -/* - * Relinquish the interface unit to another device. - */ -static void -pppasyncrelinq(sc) - struct ppp_softc *sc; -{ - int s; - - s = spltty(); - if (sc->sc_outm) { - m_freem(sc->sc_outm); - sc->sc_outm = NULL; - } - if (sc->sc_m) { - m_freem(sc->sc_m); - sc->sc_m = NULL; - } - if (sc->sc_flags & SC_TIMEOUT) { - untimeout(ppp_timeout, (void *) sc); - sc->sc_flags &= ~SC_TIMEOUT; - } - splx(s); -} - -/* - * Line specific (tty) read routine. - */ -int -pppread(tp, uio, flag) - register struct tty *tp; - struct uio *uio; - int flag; -{ - register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc; - struct mbuf *m, *m0; - register int s; - int error = 0; - - if (sc == NULL) - return 0; - /* - * Loop waiting for input, checking that nothing disasterous - * happens in the meantime. - */ - s = spltty(); - for (;;) { - if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) { - splx(s); - return 0; - } - if (sc->sc_inq.ifq_head != NULL) - break; - if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0 - && (tp->t_state & TS_ISOPEN)) { - splx(s); - return 0; /* end of file */ - } - if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) { - splx(s); - return (EWOULDBLOCK); - } - error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, "ttyin", 0); - if (error) { - splx(s); - return error; - } - } - - /* Pull place-holder byte out of canonical queue */ - getc(&tp->t_canq); - - /* Get the packet from the input queue */ - IF_DEQUEUE(&sc->sc_inq, m0); - splx(s); - - for (m = m0; m && uio->uio_resid; m = m->m_next) - if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0) - break; - m_freem(m0); - return (error); -} - -/* - * Line specific (tty) write routine. - */ -int -pppwrite(tp, uio, flag) - register struct tty *tp; - struct uio *uio; - int flag; -{ - register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc; - struct mbuf *m, *m0, **mp; - struct sockaddr dst; - int len, error; - - if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) - return 0; /* wrote 0 bytes */ - if (tp->t_line != PPPDISC) - return (EINVAL); - if (sc == NULL || tp != (struct tty *) sc->sc_devp) - return EIO; - if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN || - uio->uio_resid < PPP_HDRLEN) - return (EMSGSIZE); - for (mp = &m0; uio->uio_resid; mp = &m->m_next) { - MGET(m, M_WAIT, MT_DATA); - if ((*mp = m) == NULL) { - m_freem(m0); - return (ENOBUFS); - } - m->m_len = 0; - if (uio->uio_resid >= MCLBYTES / 2) - MCLGET(m, M_DONTWAIT); - len = M_TRAILINGSPACE(m); - if (len > uio->uio_resid) - len = uio->uio_resid; - if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) { - m_freem(m0); - return (error); - } - m->m_len = len; - } - dst.sa_family = AF_UNSPEC; - bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN); - m0->m_data += PPP_HDRLEN; - m0->m_len -= PPP_HDRLEN; - return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0)); -} - -/* - * Line specific (tty) ioctl routine. - * This discipline requires that tty device drivers call - * the line specific l_ioctl routine from their ioctl routines. - */ -/* ARGSUSED */ -int -ppptioctl(tp, cmd, data, flag, p) - struct tty *tp; - int cmd; - caddr_t data; - int flag; - struct proc *p; -{ - struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc; - int error, s; - - if (sc == NULL || tp != (struct tty *) sc->sc_devp) - return -1; - - error = 0; - switch (cmd) { - case PPPIOCSASYNCMAP: - if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) - break; - sc->sc_asyncmap[0] = *(u_int *)data; - break; - - case PPPIOCGASYNCMAP: - *(u_int *)data = sc->sc_asyncmap[0]; - break; - - case PPPIOCSRASYNCMAP: - if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) - break; - sc->sc_rasyncmap = *(u_int *)data; - break; - - case PPPIOCGRASYNCMAP: - *(u_int *)data = sc->sc_rasyncmap; - break; - - case PPPIOCSXASYNCMAP: - if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) - break; - s = spltty(); - bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); - sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */ - sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */ - sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */ - splx(s); - break; - - case PPPIOCGXASYNCMAP: - bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap)); - break; - - default: - error = pppioctl(sc, cmd, data, flag, p); - if (error == 0 && cmd == PPPIOCSMRU) - pppgetm(sc); - } - - return error; -} - -/* - * 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 -}; - -/* - * Calculate a new FCS given the current FCS and the new data. - */ -static u_short -pppfcs(fcs, cp, len) - register u_short fcs; - register u_char *cp; - register int len; -{ - while (len--) - fcs = PPP_FCS(fcs, *cp++); - return (fcs); -} - -/* - * This gets called at splsoftnet from if_ppp.c at various times - * when there is data ready to be sent. - */ -static void -pppasyncstart(sc) - register struct ppp_softc *sc; -{ - register struct tty *tp = (struct tty *) sc->sc_devp; - register struct mbuf *m; - register int len; - register u_char *start, *stop, *cp; - int n, ndone, done, idle; - struct mbuf *m2; - int s; - - idle = 0; - while (CCOUNT(&tp->t_outq) < PPP_HIWAT) { - /* - * See if we have an existing packet partly sent. - * If not, get a new packet and start sending it. - */ - m = sc->sc_outm; - if (m == NULL) { - /* - * Get another packet to be sent. - */ - m = ppp_dequeue(sc); - if (m == NULL) { - idle = 1; - break; - } - - /* - * The extra PPP_FLAG will start up a new packet, and thus - * will flush any accumulated garbage. We do this whenever - * the line may have been idle for some time. - */ - if (CCOUNT(&tp->t_outq) == 0) { - ++sc->sc_stats.ppp_obytes; - (void) putc(PPP_FLAG, &tp->t_outq); - } - - /* Calculate the FCS for the first mbuf's worth. */ - sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len); - sc->sc_if.if_lastchange = time; - } - - for (;;) { - start = mtod(m, u_char *); - len = m->m_len; - stop = start + len; - while (len > 0) { - /* - * Find out how many bytes in the string we can - * handle without doing something special. - */ - for (cp = start; cp < stop; cp++) - if (ESCAPE_P(*cp)) - break; - n = cp - start; - if (n) { - /* NetBSD (0.9 or later), 4.3-Reno or similar. */ - ndone = n - b_to_q(start, n, &tp->t_outq); - len -= ndone; - start += ndone; - sc->sc_stats.ppp_obytes += ndone; - - if (ndone < n) - break; /* packet doesn't fit */ - } - /* - * If there are characters left in the mbuf, - * the first one must be special. - * Put it out in a different form. - */ - if (len) { - s = spltty(); - if (putc(PPP_ESCAPE, &tp->t_outq)) - break; - if (putc(*start ^ PPP_TRANS, &tp->t_outq)) { - (void) unputc(&tp->t_outq); - splx(s); - break; - } - splx(s); - sc->sc_stats.ppp_obytes += 2; - start++; - len--; - } - } - - /* - * If we didn't empty this mbuf, remember where we're up to. - * If we emptied the last mbuf, try to add the FCS and closing - * flag, and if we can't, leave sc_outm pointing to m, but with - * m->m_len == 0, to remind us to output the FCS and flag later. - */ - done = len == 0; - if (done && m->m_next == NULL) { - u_char *p, *q; - int c; - u_char endseq[8]; - - /* - * We may have to escape the bytes in the FCS. - */ - p = endseq; - c = ~sc->sc_outfcs & 0xFF; - if (ESCAPE_P(c)) { - *p++ = PPP_ESCAPE; - *p++ = c ^ PPP_TRANS; - } else - *p++ = c; - c = (~sc->sc_outfcs >> 8) & 0xFF; - if (ESCAPE_P(c)) { - *p++ = PPP_ESCAPE; - *p++ = c ^ PPP_TRANS; - } else - *p++ = c; - *p++ = PPP_FLAG; - - /* - * Try to output the FCS and flag. If the bytes - * don't all fit, back out. - */ - s = spltty(); - for (q = endseq; q < p; ++q) - if (putc(*q, &tp->t_outq)) { - done = 0; - for (; q > endseq; --q) - unputc(&tp->t_outq); - break; - } - splx(s); - if (done) - sc->sc_stats.ppp_obytes += q - endseq; - } - - if (!done) { - /* remember where we got to */ - m->m_data = start; - m->m_len = len; - break; - } - - /* Finished with this mbuf; free it and move on. */ - MFREE(m, m2); - m = m2; - if (m == NULL) { - /* Finished a packet */ - break; - } - sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len); - } - - /* - * If m == NULL, we have finished a packet. - * If m != NULL, we've either done as much work this time - * as we need to, or else we've filled up the output queue. - */ - sc->sc_outm = m; - if (m) - break; - } - - /* Call pppstart to start output again if necessary. */ - s = spltty(); - pppstart(tp); - - /* - * This timeout is needed for operation on a pseudo-tty, - * because the pty code doesn't call pppstart after it has - * drained the t_outq. - */ - if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) { - timeout(ppp_timeout, (void *) sc, 1); - sc->sc_flags |= SC_TIMEOUT; - } - - splx(s); -} - -/* - * This gets called when a received packet is placed on - * the inq, at splsoftnet. - */ -static void -pppasyncctlp(sc) - struct ppp_softc *sc; -{ - struct tty *tp; - int s; - - /* Put a placeholder byte in canq for ttselect()/ttnread(). */ - s = spltty(); - tp = (struct tty *) sc->sc_devp; - putc(0, &tp->t_canq); - ttwakeup(tp); - splx(s); -} - -/* - * Start output on async tty interface. If the transmit queue - * has drained sufficiently, arrange for pppasyncstart to be - * called later at splsoftnet. - * Called at spltty or higher. - */ -int -pppstart(tp) - register struct tty *tp; -{ - register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc; - - /* - * If there is stuff in the output queue, send it now. - * We are being called in lieu of ttstart and must do what it would. - */ - if (tp->t_oproc != NULL) - (*tp->t_oproc)(tp); - - /* - * If the transmit queue has drained and the tty has not hung up - * or been disconnected from the ppp unit, then tell if_ppp.c that - * we need more output. - */ - if (CCOUNT(&tp->t_outq) < PPP_LOWAT - && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) - && sc != NULL && tp == (struct tty *) sc->sc_devp) { - ppp_restart(sc); - } - - return 0; -} - -/* - * Timeout routine - try to start some more output. - */ -static void -ppp_timeout(x) - void *x; -{ - struct ppp_softc *sc = (struct ppp_softc *) x; - struct tty *tp = (struct tty *) sc->sc_devp; - int s; - - s = spltty(); - sc->sc_flags &= ~SC_TIMEOUT; - pppstart(tp); - splx(s); -} - -/* - * Allocate enough mbuf to handle current MRU. - */ -static void -pppgetm(sc) - register struct ppp_softc *sc; -{ - struct mbuf *m, **mp; - int len; - - mp = &sc->sc_m; - for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){ - if ((m = *mp) == NULL) { - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) - break; - *mp = m; - MCLGET(m, M_DONTWAIT); - } - len -= M_DATASIZE(m); - mp = &m->m_next; - } -} - -/* - * tty interface receiver interrupt. - */ -static unsigned paritytab[8] = { - 0x96696996, 0x69969669, 0x69969669, 0x96696996, - 0x69969669, 0x96696996, 0x96696996, 0x69969669 -}; - -int -pppinput(c, tp) - int c; - register struct tty *tp; -{ - register struct ppp_softc *sc; - struct mbuf *m; - int ilen, s; - - sc = (struct ppp_softc *) tp->t_sc; - if (sc == NULL || tp != (struct tty *) sc->sc_devp) - return 0; - - ++tk_nin; - ++sc->sc_stats.ppp_ibytes; - - if (c & TTY_FE) { - /* framing error or overrun on this char - abort packet */ - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c); - goto flush; - } - - c &= 0xff; - - /* - * Handle software flow control of output. - */ - if (tp->t_iflag & IXON) { - if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) { - if ((tp->t_state & TS_TTSTOP) == 0) { - tp->t_state |= TS_TTSTOP; - (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); - } - return 0; - } - if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) { - tp->t_state &= ~TS_TTSTOP; - if (tp->t_oproc != NULL) - (*tp->t_oproc)(tp); - return 0; - } - } - - s = spltty(); - if (c & 0x80) - sc->sc_flags |= SC_RCV_B7_1; - else - sc->sc_flags |= SC_RCV_B7_0; - if (paritytab[c >> 5] & (1 << (c & 0x1F))) - sc->sc_flags |= SC_RCV_ODDP; - else - sc->sc_flags |= SC_RCV_EVNP; - splx(s); - - if (sc->sc_flags & SC_LOG_RAWIN) - ppplogchar(sc, c); - - if (c == PPP_FLAG) { - ilen = sc->sc_ilen; - sc->sc_ilen = 0; - - if (sc->sc_rawin_count > 0) - ppplogchar(sc, -1); - - /* - * If SC_ESCAPED is set, then we've seen the packet - * abort sequence "}~". - */ - if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED) - || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) { - s = spltty(); - sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */ - if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){ - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: bad fcs %x, pkt len %d\n", - sc->sc_if.if_unit, sc->sc_fcs, ilen); - sc->sc_if.if_ierrors++; - sc->sc_stats.ppp_ierrors++; - } else - sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED); - splx(s); - return 0; - } - - if (ilen < PPP_HDRLEN + PPP_FCSLEN) { - if (ilen) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen); - s = spltty(); - sc->sc_if.if_ierrors++; - sc->sc_stats.ppp_ierrors++; - sc->sc_flags |= SC_PKTLOST; - splx(s); - } - return 0; - } - - /* - * Remove FCS trailer. Somewhat painful... - */ - ilen -= 2; - if (--sc->sc_mc->m_len == 0) { - for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next) - ; - sc->sc_mc = m; - } - sc->sc_mc->m_len--; - - /* excise this mbuf chain */ - m = sc->sc_m; - sc->sc_m = sc->sc_mc->m_next; - sc->sc_mc->m_next = NULL; - - ppppktin(sc, m, sc->sc_flags & SC_PKTLOST); - if (sc->sc_flags & SC_PKTLOST) { - s = spltty(); - sc->sc_flags &= ~SC_PKTLOST; - splx(s); - } - - pppgetm(sc); - return 0; - } - - if (sc->sc_flags & SC_FLUSH) { - if (sc->sc_flags & SC_LOG_FLUSH) - ppplogchar(sc, c); - return 0; - } - - if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) - return 0; - - s = spltty(); - if (sc->sc_flags & SC_ESCAPED) { - sc->sc_flags &= ~SC_ESCAPED; - c ^= PPP_TRANS; - } else if (c == PPP_ESCAPE) { - sc->sc_flags |= SC_ESCAPED; - splx(s); - return 0; - } - splx(s); - - /* - * Initialize buffer on first octet received. - * First octet could be address or protocol (when compressing - * address/control). - * Second octet is control. - * Third octet is first or second (when compressing protocol) - * octet of protocol. - * Fourth octet is second octet of protocol. - */ - if (sc->sc_ilen == 0) { - /* reset the first input mbuf */ - if (sc->sc_m == NULL) { - pppgetm(sc); - if (sc->sc_m == NULL) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit); - goto flush; - } - } - m = sc->sc_m; - m->m_len = 0; - m->m_data = M_DATASTART(sc->sc_m); - sc->sc_mc = m; - sc->sc_mp = mtod(m, char *); - sc->sc_fcs = PPP_INITFCS; - if (c != PPP_ALLSTATIONS) { - if (sc->sc_flags & SC_REJ_COMP_AC) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: garbage received: 0x%x (need 0xFF)\n", - sc->sc_if.if_unit, c); - goto flush; - } - *sc->sc_mp++ = PPP_ALLSTATIONS; - *sc->sc_mp++ = PPP_UI; - sc->sc_ilen += 2; - m->m_len += 2; - } - } - if (sc->sc_ilen == 1 && c != PPP_UI) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: missing UI (0x3), got 0x%x\n", - sc->sc_if.if_unit, c); - goto flush; - } - if (sc->sc_ilen == 2 && (c & 1) == 1) { - /* a compressed protocol */ - *sc->sc_mp++ = 0; - sc->sc_ilen++; - sc->sc_mc->m_len++; - } - if (sc->sc_ilen == 3 && (c & 1) == 0) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit, - (sc->sc_mp[-1] << 8) + c); - goto flush; - } - - /* packet beyond configured mru? */ - if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: packet too big\n", sc->sc_if.if_unit); - goto flush; - } - - /* is this mbuf full? */ - m = sc->sc_mc; - if (M_TRAILINGSPACE(m) <= 0) { - if (m->m_next == NULL) { - pppgetm(sc); - if (m->m_next == NULL) { - if (sc->sc_flags & SC_DEBUG) - printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit); - goto flush; - } - } - sc->sc_mc = m = m->m_next; - m->m_len = 0; - m->m_data = M_DATASTART(m); - sc->sc_mp = mtod(m, char *); - } - - ++m->m_len; - *sc->sc_mp++ = c; - sc->sc_fcs = PPP_FCS(sc->sc_fcs, c); - return 0; - - flush: - if (!(sc->sc_flags & SC_FLUSH)) { - s = spltty(); - sc->sc_if.if_ierrors++; - sc->sc_stats.ppp_ierrors++; - sc->sc_flags |= SC_FLUSH; - splx(s); - if (sc->sc_flags & SC_LOG_FLUSH) - ppplogchar(sc, c); - } - return 0; -} - -#define MAX_DUMP_BYTES 128 - -static void -ppplogchar(sc, c) - struct ppp_softc *sc; - int c; -{ - if (c >= 0) - sc->sc_rawin[sc->sc_rawin_count++] = c; - if (sc->sc_rawin_count >= sizeof(sc->sc_rawin) - || (c < 0 && sc->sc_rawin_count > 0)) { - printf("ppp%d input: ", sc->sc_if.if_unit); - pppdumpb(sc->sc_rawin, sc->sc_rawin_count); - sc->sc_rawin_count = 0; - } -} - -static void -pppdumpb(b, l) - u_char *b; - int l; -{ - char buf[3*MAX_DUMP_BYTES+4]; - char *bp = buf; - static char digits[] = "0123456789abcdef"; - - while (l--) { - if (bp >= buf + sizeof(buf) - 3) { - *bp++ = '>'; - break; - } - *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */ - *bp++ = digits[*b++ & 0xf]; - *bp++ = ' '; - } - - *bp = 0; - printf("%s\n", buf); -} - -#endif /* NPPP > 0 */ diff --git a/c/src/libnetworking/pppd/pppd.8 b/c/src/libnetworking/pppd/pppd.8 new file mode 100644 index 0000000000..227345ff5f --- /dev/null +++ b/c/src/libnetworking/pppd/pppd.8 @@ -0,0 +1,1480 @@ +.\" manual page [] for pppd 2.3 +.\" $Id$ +.\" 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 +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. A value for this +option from a privileged source cannot be overridden by a +non-privileged user. +.TP +.I +Set the baud rate to (a decimal number). On systems such as +4.4BSD and NetBSD, any speed can be specified. Other systems +(e.g. SunOS) allow only a limited set of speeds. +.TP +.B asyncmap \fI +Set the async character map to . 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. This option is the default if the +system has a default route. If neither this option nor the +\fInoauth\fR option is specified, pppd will only allow the peer to use +IP addresses to which the system does not already have a route. +.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. A value +for this option from a privileged source cannot be overridden by a +non-privileged user. +.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, the +\fInocrtscts\fR, the \fIcdtrcts\fR nor the \fInocdtrcts\fR option +is given, the hardware flow control setting for the serial port is +left unchanged. +Some serial ports (such as Macintosh serial ports) lack a true +RTS output. Such serial ports use this mode to implement +unidirectional flow control. The serial port will +suspend transmission when requested by the modem (via CTS) +but will be unable to request the modem stop sending to the +computer. This mode retains the ability to use DTR as +a modem control line. +.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. A value for this option from a privileged +source cannot be overridden by a non-privileged user. +.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 init \fIscript +Run the executable or shell command specified by \fIscript\fR to +initialize the serial line. This script would typically use the +chat(8) program to configure the modem to enable auto answer. A value +for this option from a privileged source cannot be overridden by a +non-privileged user. +.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 \fB:\fI +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\fR,\fI +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 ,\fR option. Otherwise the +identifier is randomized. +.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 +is currently only available under NetBSD, and then only +if both the kernel and pppd were compiled with PPP_FILTER defined. +.TP +.B allow-ip \fIaddress(es) +Allow peers to use the given IP address or subnet without +authenticating themselves. The parameter is parsed as for each +element of the list of allowed IP addresses in the secrets files (see +the AUTHENTICATION section below). +.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 cdtrcts +Use a non-standard hardware flow control (i.e. DTR/CTS) to control +the flow of data on the serial port. If neither the \fIcrtscts\fR, +the \fInocrtscts\fR, the \fIcdtrcts\fR nor the \fInocdtrcts\fR +option is given, the hardware flow control setting for the serial +port is left unchanged. +Some serial ports (such as Macintosh serial ports) lack a true +RTS output. Such serial ports use this mode to implement true +bi-directional flow control. The sacrifice is that this flow +control mode does not permit using DTR as a modem control line. +.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 connect-delay \fIn +Wait for up \fIn\fR milliseconds after the connect script finishes for +a valid PPP packet from the peer. At the end of this time, or when a +valid PPP packet is received from the peer, pppd will commence +negotiation by sending its first LCP packet. The default value is +1000 (1 second). This wait period only applies if the \fBconnect\fR +or \fBpty\fR option is used. +.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 conjuction 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 hide-password +When logging the contents of PAP packets, this option causes pppd to +exclude the password string from the log. This is the default. +.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 +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 nuber 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 ktune +Enables pppd to alter kernel settings as appropriate. Under Linux, +pppd will enable IP forwarding (i.e. set /proc/sys/net/ipv4/ip_forward +to 1) if the \fIproxyarp\fR option is used, and will enable the +dynamic IP address option (i.e. set /proc/sys/net/ipv4/ip_dynaddr to +1) in demand mode if the local address changes. +.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 linkname \fIname\fR +Sets the logical name of the link to \fIname\fR. Pppd will create a +file named \fBppp-\fIname\fB.pid\fR in /var/run (or /etc/ppp on some +systems) containing its process ID. This can be useful in determining +which instance of pppd is responsible for the link to a given peer +system. This is a privileged option. +.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 logfd \fIn +Send log messages to file descriptor \fIn\fR. Pppd will send log +messages to at most one file or file descriptor (as well as sending +the log messages to syslog), so this option and the \fBlogfile\fR +option are mutually exclusive. The default is for pppd to send log +messages to stdout (file descriptor 1), unless the serial port is +already open on stdout. +.TP +.B logfile \fIfilename +Append log messages to the file \fIfilename\fR (as well as sending the +log messages to syslog). The file is opened with the privileges of +the user who invoked pppd, in append mode. +.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 maxfail \fIn +Terminate after \fIn\fR consecutive failed connection attempts. A +value of 0 means no limit. The default value is 10. +.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 +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 +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. (Note: on some platforms, pppd +will always use 255.255.255.255 for the netmask, if that is the only +appropriate value for a point-to-point interface.) +.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. +.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 nor the +\fIcdtrcts\fR nor the \fInodtrcts\fR option is given, the hardware +flow control setting for the serial port is left unchanged. +.TP +.B nodtrcts +This option is a synonym for \fInocrtscts\fR. Either of these options will +disable both forms of hardware flow control. +.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 noktune +Opposite of the \fIktune\fR option; disables pppd from changing system +settings. +.TP +.B nolog +Do not send log messages to a file or file descriptor. This option +cancels the \fBlogfd\fR and \fBlogfile\fR options. +.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 notty +Normally, pppd requires a terminal device. With this option, pppd +will allocate itself a pseudo-tty master/slave pair and use the slave +as its terminal device. Pppd will create a child process to act as a +`character shunt' to transfer characters between the pseudo-tty master +and its standard input and output. Thus pppd will transmit characters +on its standard output and receive characters on its standard input +even if they are not terminal devices. This option increases the +latency and CPU overhead of transferring data over the ppp interface +as all of the characters sent and received must flow through the +character shunt process. An explicit device name may not be given if +this option is used. +.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 plugin \fIfilename +Load the shared library object file \fIfilename\fR as a plugin. This +is a privileged option. +.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 privgroup \fIgroup-name +Allows members of group \fIgroup-name\fR to use privileged options. +This is a privileged option. Use of this option requires care as +there is no guarantee that members of \fIgroup-name\fR cannot use pppd +to become root themselves. Consider it equivalent to putting the +members of \fIgroup-name\fR in the kmem or disk group. +.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 pty \fIscript +Specifies that the command \fIscript\fR is to be used to communicate +rather than a specific terminal device. Pppd will allocate itself a +pseudo-tty master/slave pair and use the slave as its terminal +device. The \fIscript\fR will be run in a child process with the +pseudo-tty master as its standard input and output. An explicit +device name may not be given if this option is used. (Note: if the +\fIrecord\fR option is used in conjuction with the \fIpty\fR option, +the child process will have pipes on its standard input and output.) +.TP +.B receive-all +With this option, pppd will accept all control characters from the +peer, including those marked in the receive asyncmap. Without this +option, pppd will discard those characters as specified in RFC1662. +This option should only be needed if the peer is buggy. +.TP +.B record \fIfilename +Specifies that pppd should record all characters sent and received to +a file named \fIfilename\fR. This file is opened in append mode, +using the user's user-ID and permissions. This option is implemented +using a pseudo-tty and a process to transfer characters between the +pseudo-tty and the real serial device, so it will increase the latency +and CPU overhead of transferring data over the ppp interface. The +characters are stored in a tagged format with timestamps, which can be +displayed in readable form using the pppdump(8) program. +.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 show-password +When logging the contents of PAP packets, this option causes pppd to +show the password string in the log message. +.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 sync +Use synchronous HDLC serial encoding instead of asynchronous. +The device used by pppd with this option must have sync support. +Currently supports Microgate SyncLink adapters +under Linux and FreeBSD 2.2.8 and later. +.TP +.B updetach +With this option, pppd will detach from its controlling terminal once +it has successfully established the ppp connection (to the point where +the first network control protocol, usually the IP control protocol, +has come up). +.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). This option is not normally needed since the +\fIname\fR option is privileged. +.TP +.B usepeerdns +Ask the peer for up to 2 DNS server addresses. The addresses supplied +by the peer (if any) are passed to the /etc/ppp/ip-up script in the +environment variables DNS1 and DNS2. In addition, pppd will create an +/etc/ppp/resolv.conf file containing one or two nameserver lines with +the address(es) supplied by the peer. +.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. A value for this option from a privileged source cannot be +overridden by a non-privileged user. +.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. This control is provided through restrictions on which IP +addresses the peer may use, based on its authenticated identity (if +any), and through restrictions on which options a non-privileged user +may use. Several of pppd's options are privileged, in particular +those which permit potentially insecure configurations; these options +are only accepted in files which are under the control of the system +administrator, or if pppd is being run by root. +.PP +The default behaviour of pppd is to allow an unauthenticated peer to +use a given IP address only if the system does not already have a +route to that IP address. For example, a system with a +permanent connection to the wider internet will normally have a +default route, and thus all peers will have to authenticate themselves +in order to set up a connection. On such a system, the \fIauth\fR +option is the default. On the other hand, a system where the +PPP link is the only connection to the internet will not normally have +a default route, so the peer will be able to use almost any IP address +without authenticating itself. +.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. +.PP +When opening the device, pppd uses either the invoking user's user ID +or the root UID (that is, 0), depending on whether the device name was +specified by the user or the system administrator. If the device name +comes from a privileged source, that is, /etc/ppp/options or an +options file read using the \fIcall\fR option, pppd uses full root +privileges when opening the device. Thus, by creating an appropriate +file under /etc/ppp/peers, the system administrator can allow users to +establish a ppp connection via a device which they would not normally +have permission to access. Otherwise pppd uses the invoking user's +real UID when opening the device. +.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 a 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. 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 +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, 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. In this form, the address may be followed +by a plus sign ("+") to indicate that one address from the subnet is +authorized, based on the ppp network interface unit number in use. +In this case, the host part of the address will be set to the unit +number plus one. +.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 +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 EXIT STATUS +The exit status of pppd is set to indicate whether any error was +detected, or the reason for the link being terminated. The values +used are: +.TP +.B 0 +Pppd has detached, or otherwise the connection was successfully +established and terminated at the peer's request. +.TP +.B 1 +An immediately fatal error of some kind occurred, such as an essential +system call failing, or running out of virtual memory. +.TP +.B 2 +An error was detected in processing the options given, such as two +mutually exclusive options being used. +.TP +.B 3 +Pppd is not setuid-root and the invoking user is not root. +.TP +.B 4 +The kernel does not support PPP, for example, the PPP kernel driver is +not included or cannot be loaded. +.TP +.B 5 +Pppd terminated because it was sent a SIGINT, SIGTERM or SIGHUP +signal. +.TP +.B 6 +The serial port could not be locked. +.TP +.B 7 +The serial port could not be opened. +.TP +.B 8 +The connect script failed (returned a non-zero exit status). +.TP +.B 9 +The command specified as the argument to the \fIpty\fR option could +not be run. +.TP +.B 10 +The PPP negotiation failed, that is, it didn't reach the point where +at least one network protocol (e.g. IP) was running. +.TP +.B 11 +The peer system failed (or refused) to authenticate itself. +.TP +.B 12 +The link was established successfully and terminated because it was +idle. +.TP +.B 13 +The link was established successfully and terminated because the +connect time limit was reached. +.TP +.B 14 +Callback was negotiated and an incoming call should arrive shortly. +.TP +.B 15 +The link was terminated because the peer is not responding to echo +requests. +.TP +.B 16 +The link was terminated by the modem hanging up. +.TP +.B 17 +The PPP negotiation failed because serial loopback was detected. +.TP +.B 18 +The init script failed (returned a non-zero exit status). +.TP +.B 19 +We failed to authenticate ourselves to the peer. +.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 ORIG_UID +The real user-id of the user who invoked pppd. +.TP +.B PPPLOGNAME +The username of the real user-id that invoked pppd. This is always set. +.P +For the ip-down and auth-down scripts, pppd also sets the following +variables giving statistics for the connection: +.TP +.B CONNECT_TIME +The number of seconds from when the PPP negotiation started until the +connection was terminated. +.TP +.B BYTES_SENT +The number of bytes sent (at the level of the serial port) during the +connection. +.TP +.B BYTES_RCVD +The number of bytes received (at the level of the serial port) during +the connection. +.TP +.B LINKNAME +The logical name of the link, set with the \fIlinkname\fR option. +.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 /var/run/ppp-\fIname\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp-\fIname\fB.pid \fR(others) +Process-ID for pppd process for logical link \fIname\fR (see the +\fIlinkname\fR option). +.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. +.SH SEE ALSO +.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. +.TP +.B RFC2472 +Haskin, D. +.I IP Version 6 over PPP +December 1998. +.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/c/src/libnetworking/pppd/pppd.h b/c/src/libnetworking/pppd/pppd.h index b33b6a32de..e30ddfe55e 100644 --- a/c/src/libnetworking/pppd/pppd.h +++ b/c/src/libnetworking/pppd/pppd.h @@ -26,20 +26,25 @@ #ifndef __PPPD_H__ #define __PPPD_H__ -#include #include /* for FILE */ +#include /* for NGROUPS_MAX */ #include /* for MAXPATHLEN and BSD4_4, if defined */ #include /* for u_int32_t, if defined */ #include /* for struct timeval */ #include -#if __STDC__ +#if defined(__STDC__) #include #define __V(x) x #else #include #define __V(x) (va_alist) va_dcl #define const +#define volatile +#endif + +#ifdef INET6 +#include "eui64.h" #endif /* @@ -52,12 +57,92 @@ #define MAXNAMELEN 256 /* max length of hostname or name for auth */ #define MAXSECRETLEN 256 /* max length of password or secret */ +/* + * Option descriptor structure. + */ + +typedef unsigned char bool; + +enum opt_type { + o_special_noarg = 0, + o_special = 1, + o_bool, + o_int, + o_uint32, + o_string, +}; + +typedef struct { + char *name; /* name of the option */ + enum opt_type type; + void *addr; + char *description; + int flags; + void *addr2; + int upper_limit; + int lower_limit; +} option_t; + +/* Values for flags */ +#define OPT_VALUE 0xff /* mask for presupplied value */ +#define OPT_HEX 0x100 /* int option is in hex */ +#define OPT_NOARG 0x200 /* option doesn't take argument */ +#define OPT_OR 0x400 /* OR in argument to value */ +#define OPT_INC 0x800 /* increment value */ +#define OPT_PRIV 0x1000 /* privileged option */ +#define OPT_STATIC 0x2000 /* string option goes into static array */ +#define OPT_LLIMIT 0x4000 /* check value against lower limit */ +#define OPT_ULIMIT 0x8000 /* check value against upper limit */ +#define OPT_LIMITS (OPT_LLIMIT|OPT_ULIMIT) +#define OPT_ZEROOK 0x10000 /* 0 value is OK even if not within limits */ +#define OPT_NOINCR 0x20000 /* value mustn't be increased */ +#define OPT_ZEROINF 0x40000 /* with OPT_NOINCR, 0 == infinity */ +#define OPT_A2INFO 0x100000 /* addr2 -> option_info to update */ +#define OPT_A2COPY 0x200000 /* addr2 -> second location to rcv value */ +#define OPT_ENABLE 0x400000 /* use *addr2 as enable for option */ +#define OPT_PRIVFIX 0x800000 /* can't be overridden if noauth */ +#define OPT_PREPASS 0x1000000 /* do this opt in pre-pass to find device */ +#define OPT_INITONLY 0x2000000 /* option can only be set in init phase */ +#define OPT_DEVEQUIV 0x4000000 /* equiv to device name */ +#define OPT_DEVNAM (OPT_PREPASS | OPT_INITONLY | OPT_DEVEQUIV) + +#define OPT_VAL(x) ((x) & OPT_VALUE) + +#ifndef GIDSET_TYPE +#define GIDSET_TYPE gid_t +#endif + +/* Structure representing a list of permitted IP addresses. */ +struct permitted_ip { + int permit; /* 1 = permit, 0 = forbid */ + u_int32_t base; /* match if (addr & mask) == base */ + u_int32_t mask; /* base and mask are in network byte order */ +}; + +/* + * Unfortunately, the linux kernel driver uses a different structure + * for statistics from the rest of the ports. + * This structure serves as a common representation for the bits + * pppd needs. + */ +struct pppd_stats { + unsigned int bytes_in; + unsigned int bytes_out; +}; + +/* Used for storing a sequence of words. Usually malloced. */ +struct wordlist { + struct wordlist *next; + char *word; +}; + /* * Global variables. */ +extern int kill_link; /* Signal to terminate processing loop */ extern int hungup; /* Physical layer has disconnected */ -extern int interfunit; /* Interface unit number */ +extern int pppifunit; /* Interface unit number */ extern char ifname[]; /* Interface name */ extern int ttyfd; /* Serial device file descriptor */ extern char hostname[]; /* Our hostname */ @@ -71,6 +156,21 @@ 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 */ +extern GIDSET_TYPE groups[NGROUPS_MAX]; /* groups the user is in */ +extern int ngroups; /* How many groups valid in groups */ +extern struct pppd_stats link_stats; /* byte/packet counts etc. for link */ +extern int using_pty; /* using pty as device (notty or pty opt.) */ +extern int log_to_fd; /* logging to this fd as well as syslog */ +extern char *no_ppp_msg; /* message to print if ppp not in kernel */ +extern volatile int status; /* exit status for pppd */ +extern int devnam_fixed; /* can no longer change devnam */ +extern int unsuccess; /* # unsuccessful connection attempts */ +extern int do_callback; /* set if we want to do callback next */ +extern int doing_callback; /* set if this is a callback */ + +/* Values for do_callback and doing_callback */ +#define CALLBACK_DIALIN 1 /* we are expecting the call back */ +#define CALLBACK_DIALOUT 2 /* we are dialling out to call back */ /* * Variables set by command-line options. @@ -79,60 +179,71 @@ extern int detached; /* Have detached from controlling tty */ 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 char devnam[MAXPATHLEN]; /* Device name */ extern int crtscts; /* Use hardware flow control */ -extern int modem; /* Use modem control lines */ +extern bool 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 bool lockflag; /* Create lock file to lock the serial dev */ +extern bool nodetach; /* Don't detach from controlling tty */ +extern bool updetach; /* Detach from controlling tty when link up */ +extern char *initializer; /* Script to initialize physical link */ +extern char *connect_script; /* Script to establish physical link */ +extern char *disconnect_script; /* Script to disestablish physical link */ +extern char *welcomer; /* Script to welcome client after connection */ +extern char *ptycommand; /* Command to run on other side of pty */ 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 user[MAXNAMELEN];/* Our name for authenticating ourselves */ +extern char passwd[MAXSECRETLEN]; /* Password for PAP or CHAP */ +extern bool auth_required; /* Peer is required to authenticate */ +extern bool persist; /* Reopen link after it goes down */ +extern bool uselogin; /* Use /etc/passwd for checking PAP */ +extern char our_name[MAXNAMELEN];/* Our name for authentication purposes */ +extern char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ +extern bool explicit_remote;/* remote_name specified with remotename opt */ +extern bool demand; /* Do dial-on-demand */ extern char *ipparam; /* Extra parameter for ip up/down scripts */ -extern int cryptpap; /* Others' PAP passwords are encrypted */ +extern bool 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 */ +extern bool holdoff_specified; /* true if user gave a holdoff value */ +extern bool notty; /* Stdin/out is not a tty */ +extern char *record_file; /* File to record chars sent/received */ +extern bool sync_serial; /* Device is synchronous serial device */ +extern int maxfail; /* Max # of unsuccessful connection attempts */ +extern char linkname[MAXPATHLEN]; /* logical name for link */ +extern bool tune_kernel; /* May alter kernel settings as necessary */ +extern int connect_delay; /* Time to delay after connect script */ + #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 */ +extern bool ms_lanman; /* Use LanMan password instead of NT */ /* Has meaning only with MS-CHAP challenges */ #endif +extern char *current_option; /* the name of the option being parsed */ +extern int privileged_option; /* set iff the current option came from root */ +extern char *option_source; /* string saying where the option came from */ + /* * 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 +#define PHASE_SERIALCONN 2 +#define PHASE_DORMANT 3 +#define PHASE_ESTABLISH 4 +#define PHASE_AUTHENTICATE 5 +#define PHASE_CALLBACK 6 +#define PHASE_NETWORK 7 +#define PHASE_RUNNING 8 +#define PHASE_TERMINATE 9 +#define PHASE_DISCONNECT 10 +#define PHASE_HOLDOFF 11 /* * The following struct gives the addresses of procedures to call @@ -160,8 +271,10 @@ struct protent { void *arg)); /* Process a received data packet */ void (*datainput) __P((int unit, u_char *pkt, int len)); - int enabled_flag; /* 0 iff protocol is disabled */ + bool enabled_flag; /* 0 iff protocol is disabled */ char *name; /* Text name of protocol */ + char *data_name; /* Text name of corresponding data protocol */ + option_t *options; /* List of command-line options */ /* Check requested options, assign defaults */ void (*check_options) __P((void)); /* Configure interface for demand-dial */ @@ -178,40 +291,45 @@ extern struct protent *protocols[]; */ /* Procedures exported from main.c. */ -void detach __P((void)); /* Detach from controlling tty */ void die __P((int)); /* Cleanup and exit */ void quit __P((void)); /* like die(1) */ void novm __P((char *)); /* Say we ran out of memory, and die */ -void my_timeout __P((void (*func)(void *), void *arg, int t)); +void ppptimeout __P((void (*func)(void *), void *arg, int t)); /* Call func(arg) after t seconds */ void untimeout __P((void (*func)(void *), void *arg)); /* Cancel call to func(arg) */ -int run_program __P((char *prog, char **args, int must_exist)); - /* Run program prog with args in child */ -void demuxprotrej __P((int, int)); - /* Demultiplex a Protocol-Reject */ -void format_packet __P((u_char *, int, void (*) (void *, char *, ...), - void *)); /* Format a packet in human-readable form */ +void update_link_stats __P((int)); /* Get stats at link termination */ +void new_phase __P((int)); /* signal start of new phase */ + +/* Procedures exported from utils.c. */ void log_packet __P((u_char *, int, char *, int)); /* Format a packet and log it with syslog */ void print_string __P((char *, int, void (*) (void *, char *, ...), void *)); /* Format a string for output */ -int fmtmsg __P((char *, int, char *, ...)); /* sprintf++ */ -int vfmtmsg __P((char *, int, char *, va_list)); /* vsprintf++ */ -void script_setenv __P((char *, char *)); /* set script env var */ -void script_unsetenv __P((char *)); /* unset script env var */ -/* My procedures */ -int connect_stb(); -int disconnect_stb(); -int pppdmain(int, char*[]); -int chatmain(char*); +int slprintf __P((char *, int, char *, ...)); /* sprintf++ */ +int vslprintf __P((char *, int, char *, va_list)); /* vsprintf++ */ +size_t strlcpy __P((char *, const char *, size_t)); /* safe strcpy */ +size_t strlcat __P((char *, const char *, size_t)); /* safe strncpy */ +void pppd_dbglog __P((char *, ...)); /* log a debug message */ +void pppd_info __P((char *, ...)); /* log an informational message */ +void pppd_notice __P((char *, ...)); /* log a notice-level message */ +void pppd_warn __P((char *, ...)); /* log a warning message */ +void pppd_error __P((char *, ...)); /* log an error message */ +void pppd_fatal __P((char *, ...)); /* log an error message and die(1) */ + +#define dbglog pppd_dbglog +#define info pppd_info +#define notice pppd_notice +#define warn pppd_warn +#define error pppd_error +#define fatal pppd_fatal /* Procedures exported from auth.c */ - void link_required __P((int)); /* we are starting to use the link */ void link_terminated __P((int)); /* we are finished with the link */ void link_down __P((int)); /* the LCP layer has left the Opened state */ void link_established __P((int)); /* the link is up; authenticate now */ +void start_networks __P((void)); /* start all the network control protos */ void np_up __P((int, int)); /* a network protocol has come up */ void np_down __P((int, int)); /* a network protocol has gone down */ void np_finished __P((int, int)); /* a network protocol no longer needs link */ @@ -223,10 +341,10 @@ void auth_withpeer_fail __P((int, int)); /* we failed to authenticate ourselves */ void auth_withpeer_success __P((int, int)); /* we successfully authenticated ourselves */ -void auth_check_options __P((void)); +int auth_check_options __P((void)); /* check authentication options supplied */ void auth_reset __P((int)); /* check what secrets we have */ -int check_passwd __P((int, char *, int, char *, int, char **, int *)); +int check_passwd __P((int, char *, int, char *, int, char **)); /* Check peer-supplied username/password */ int get_secret __P((int, char *, char *, char *, int *, int)); /* get "secret" for chap */ @@ -234,8 +352,6 @@ int auth_ip_addr __P((int, u_int32_t)); /* check if IP address is authorized */ int bad_ip_adrs __P((u_int32_t)); /* check if IP address is unreasonable */ -void check_access __P((FILE *, char *)); - /* check permissions on secrets file */ /* Procedures exported from demand.c */ void demand_conf __P((void)); /* config interface(s) for demand-dial */ @@ -244,16 +360,17 @@ void demand_unblock __P((void)); /* set all NPs to pass packets */ void demand_discard __P((void)); /* set all NPs to discard packets */ void demand_rexmit __P((int)); /* retransmit saved frames for an NP */ int loop_chars __P((unsigned char *, int)); /* process chars from loopback */ -int loop_frame __P((unsigned char *, int)); /* process frame from loopback */ +int loop_frame __P((unsigned char *, int)); /* should we bring link up? */ /* Procedures exported from sys-*.c */ void sys_init __P((void)); /* Do system-dependent initialization */ void sys_cleanup __P((void)); /* Restore system state before exiting */ -void sys_check_options __P((void)); /* Check options specified */ +int sys_check_options __P((void)); /* Check options specified */ void sys_close __P((void)); /* Clean up in a child before execing */ int ppp_available __P((void)); /* Test whether ppp kernel support exists */ -void open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */ -void establish_ppp __P((int)); /* Turn serial port into a ppp interface */ +int get_pty __P((int *, int *, char *, int)); /* Get pty master/slave */ +int open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */ +int establish_ppp __P((int)); /* Turn serial port into a ppp interface */ void restore_loop __P((void)); /* Transfer ppp unit back to loopback */ void disestablish_ppp __P((int)); /* Restore port to normal operation */ void clean_check __P((void)); /* Check if line was 8-bit clean */ @@ -263,9 +380,6 @@ void setdtr __P((int, int)); /* Raise or lower port's DTR line */ void output __P((int, u_char *, int)); /* Output a PPP packet */ void wait_input __P((struct timeval *)); /* Wait for input, with timeout */ -void wait_loop_output __P((struct timeval *)); - /* Wait for pkt from loopback, with timeout */ -void wait_time __P((struct timeval *)); /* Wait for given length of time */ int read_packet __P((u_char *)); /* Read PPP packet */ int get_loop_output __P((void)); /* Read pkts from loopback */ void ppp_send_config __P((int, int, u_int32_t, int, int)); @@ -281,16 +395,24 @@ void ccp_flags_set __P((int, int, int)); int ccp_fatal_error __P((int)); /* Test for fatal decomp error in kernel */ int get_idle_time __P((int, struct ppp_idle *)); /* Find out how long link has been idle */ +int get_ppp_stats __P((int, struct pppd_stats *)); + /* Return link statistics */ int sifvjcomp __P((int, int, int, int)); /* Configure VJ TCP header compression */ -int sifup __P((int)); /* Configure i/f up (for IP) */ +int sifup __P((int)); /* Configure i/f up for one protocol */ int sifnpmode __P((int u, int proto, enum NPmode mode)); /* Set mode for handling packets for proto */ -int sifdown __P((int)); /* Configure i/f down (for IP) */ +int sifdown __P((int)); /* Configure i/f down for one protocol */ int sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t)); - /* Configure IP addresses for i/f */ + /* Configure IPv4 addresses for i/f */ int cifaddr __P((int, u_int32_t, u_int32_t)); /* Reset i/f IP addresses */ +#ifdef INET6 +int sif6addr __P((int, eui64_t, eui64_t)); + /* Configure IPv6 addresses for i/f */ +int cif6addr __P((int, eui64_t, eui64_t)); + /* Remove an IPv6 address from i/f */ +#endif int sifdefaultroute __P((int, u_int32_t, u_int32_t)); /* Create default route through i/f */ int cifdefaultroute __P((int, u_int32_t, u_int32_t)); @@ -301,31 +423,38 @@ int cifproxyarp __P((int, u_int32_t)); /* Delete proxy ARP entry for peer */ u_int32_t GetMask __P((u_int32_t)); /* Get appropriate netmask for address */ int lock __P((char *)); /* Create lock file for device */ +int relock __P((int)); /* Rewrite lock file with new pid */ void unlock __P((void)); /* Delete previously-created lock file */ -int daemon __P((int, int)); /* Detach us from terminal session */ void logwtmp __P((const char *, const char *, const char *)); /* Write entry to wtmp file */ int get_host_seed __P((void)); /* Get host-dependent random number seed */ +int have_route_to __P((u_int32_t)); /* Check if route to addr exists */ #ifdef PPP_FILTER int set_filters __P((struct bpf_program *pass, struct bpf_program *active)); /* Set filter programs in kernel */ #endif +#ifdef IPX_CHANGE +int sipxfaddr __P((int, unsigned long, unsigned char *)); +int cipxfaddr __P((int)); +#endif /* Procedures exported from options.c */ int parse_args __P((int argc, char **argv)); /* Parse options from arguments given */ -void usage __P((void)); /* Print a usage message */ int options_from_file __P((char *filename, int must_exist, int check_prot, int privileged)); /* Parse options from an options file */ int options_from_user __P((void)); /* Parse options from user's .ppprc */ int options_for_tty __P((void)); /* Parse options from /etc/ppp/options.tty */ -void scan_args __P((int argc, char **argv)); - /* Look for tty name in command-line args */ +int options_from_list __P((struct wordlist *, int privileged)); + /* Parse options from a wordlist */ int getword __P((FILE *f, char *word, int *newlinep, char *filename)); /* Read a word from a file */ void option_error __P((char *fmt, ...)); /* Print an error message about an option */ +int int_option __P((char *, int *)); + /* Simplified number_option for decimal ints */ +void add_options __P((option_t *)); /* Add extra options */ /* * This structure is used to store information about certain @@ -338,11 +467,29 @@ struct option_info { 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; +extern struct option_info initializer_info; +extern struct option_info connect_script_info; +extern struct option_info disconnect_script_info; +extern struct option_info welcomer_info; +extern struct option_info ptycommand_info; + +/* + * Hooks to enable plugins to change various things. + */ +extern int (*new_phase_hook) __P((int)); +extern int (*idle_time_hook) __P((struct ppp_idle *)); +extern int (*holdoff_hook) __P((void)); +extern int (*pap_check_hook) __P((void)); +extern int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts)); +extern void (*pap_logout_hook) __P((void)); +extern int (*pap_passwd_hook) __P((char *user, char *passwd)); +extern void (*ip_up_hook) __P((void)); +extern void (*ip_down_hook) __P((void)); +extern void (*auth_linkup_hook) __P((void)); +extern void (*auth_linkdown_hook) __P((void)); /* * Inline versions of get/put char/short/long. @@ -383,25 +530,17 @@ extern struct option_info devnam_info; #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) my_timeout((r), (f), (t)) +#define TIMEOUT(r, f, t) ppptimeout((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); } +#define PRINTMSG(m, l) { info("Remote message: %0.*v", l, m); } /* * MAKEHEADER - Add Header fields to a packet. @@ -411,71 +550,97 @@ extern struct option_info devnam_info; PUTCHAR(PPP_UI, p); \ PUTSHORT(t, p); } -/* #define DEBUGALL */ +/* + * Exit status values. + */ +#define EXIT_OK 0 +#define EXIT_FATAL_ERROR 1 +#define EXIT_OPTION_ERROR 2 +#define EXIT_NOT_ROOT 3 +#define EXIT_NO_KERNEL_SUPPORT 4 +#define EXIT_USER_REQUEST 5 +#define EXIT_LOCK_FAILED 6 +#define EXIT_OPEN_FAILED 7 +#define EXIT_CONNECT_FAILED 8 +#define EXIT_PTYCMD_FAILED 9 +#define EXIT_NEGOTIATION_FAILED 10 +#define EXIT_PEER_AUTH_FAILED 11 +#define EXIT_IDLE_TIMEOUT 12 +#define EXIT_CONNECT_TIME 13 +#define EXIT_CALLBACK 14 +#define EXIT_PEER_DEAD 15 +#define EXIT_HANGUP 16 +#define EXIT_LOOPBACK 17 +#define EXIT_INIT_FAILED 18 +#define EXIT_AUTH_TOPEER_FAILED 19 + +/* + * Debug macros. Slightly useful for finding bugs in pppd, not particularly + * useful for finding out why your connection isn't being established. + */ #ifdef DEBUGALL #define DEBUGMAIN 1 #define DEBUGFSM 1 #define DEBUGLCP 1 #define DEBUGIPCP 1 +#define DEBUGIPV6CP 1 #define DEBUGUPAP 1 #define DEBUGCHAP 1 #endif +#define DEBUGMAIN 1 + -#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 */ -extern rtems_id pppdaemon_tid; #ifdef DEBUGMAIN -#define MAINDEBUG(x) if (debug) syslog x +#define MAINDEBUG(x) if (debug) dbglog x #else #define MAINDEBUG(x) #endif #ifdef DEBUGSYS -#define SYSDEBUG(x) if (debug) syslog x +#define SYSDEBUG(x) if (debug) dbglog x #else #define SYSDEBUG(x) #endif #ifdef DEBUGFSM -#define FSMDEBUG(x) if (debug) syslog x +#define FSMDEBUG(x) if (debug) dbglog x #else #define FSMDEBUG(x) #endif #ifdef DEBUGLCP -#define LCPDEBUG(x) if (debug) syslog x +#define LCPDEBUG(x) if (debug) dbglog x #else #define LCPDEBUG(x) #endif #ifdef DEBUGIPCP -#define IPCPDEBUG(x) if (debug) syslog x +#define IPCPDEBUG(x) if (debug) dbglog x #else #define IPCPDEBUG(x) #endif +#ifdef DEBUGIPV6CP +#define IPV6CPDEBUG(x) if (debug) dbglog x +#else +#define IPV6CPDEBUG(x) +#endif + #ifdef DEBUGUPAP -#define UPAPDEBUG(x) if (debug) syslog x +#define UPAPDEBUG(x) if (debug) dbglog x #else #define UPAPDEBUG(x) #endif #ifdef DEBUGCHAP -#define CHAPDEBUG(x) if (debug) syslog x +#define CHAPDEBUG(x) if (debug) dbglog x #else #define CHAPDEBUG(x) #endif #ifdef DEBUGIPXCP -#define IPXCPDEBUG(x) if (debug) syslog x +#define IPXCPDEBUG(x) if (debug) dbglog x #else #define IPXCPDEBUG(x) #endif diff --git a/c/src/libnetworking/pppd/pppmain.c b/c/src/libnetworking/pppd/pppmain.c deleted file mode 100644 index 4ba37a945f..0000000000 --- a/c/src/libnetworking/pppd/pppmain.c +++ /dev/null @@ -1,1314 +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[] = "$Id$"; */ -#endif - -#include -#include -/* #include */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* #include */ -#include "pppd.h" -#include "magic.h" -#include "fsm.h" -#include "lcp.h" -#include "ipcp.h" -#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 - -void SetStatusInfo(int state, char * text, int res); - -/* prototypes for routines in this file */ -int connect_script(int fd); - -/* interface vars */ -char ifname[32]; /* Interface name */ -int interfunit; /* Interface unit number */ - -char *progname; /* Name of this program */ -char hostname[MAXNAMELEN] = "dcna"; /* Our hostname */ -static char default_devnam[MAXPATHLEN]; /* name of default device */ -/*static pid_t pid; */ /* Our pid */ -static uid_t uid; /* Our real user-id */ -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 */ - - - -char *no_ppp_msg = "lack of PPP\n"; - -/* Prototypes for procedures local to this file. */ -static void cleanup(void); -static void close_tty __P((void)); -static void get_input __P((void)); -static void calltimeout __P((void)); -static struct timeval *timeleft __P((struct timeval *)); -static void holdoff_end __P((void *)); -static void reap_kids __P((void)); -/* XXX currently unused */ -#if 0 -static int device_script __P((char *[], int, int)); -static void pr_log __P((void *, char *,...)); -#endif - -extern char *ttyname __P((int)); -extern char *getlogin __P((void)); -int main __P((int, char *[])); - - - - - -/* - * 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, - &ccp_protent, -#ifdef IPX_CHANGE - &ipxcp_protent, -#endif -#ifdef AT_CHANGE - &atcp_protent, -#endif - NULL -}; - -extern int connect_stb(); - - -extern int disconnect_stb(); - - -extern struct in_addr rtems_bsdnet_nameserver[]; -extern int rtems_bsdnet_nameserver_count; -extern int __res_init(void); - -int pppdmain(argc, argv) -int argc; -char *argv[]; -{ - int i; -#if 0 - struct timeval timo; -#endif - struct protent *protp; - struct stat statbuf; -#if 0 - char t[100]; -#endif - - - phase = PHASE_INITIALIZE; - - strcpy(default_devnam, "/dev/modem"); - strcpy(devnam, "/dev/modem"); - - script_env = NULL; - -/* if (gethostname(hostname, MAXNAMELEN) < 0 ) { - die(1); - } - */ - hostname[MAXNAMELEN - 1] = 0; - - uid = 0; - privileged = uid == 0; - - /* - * 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); - - - -#if 1 - if (!ppp_available()) { - exit(1); - } -#endif - /* - * 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 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(); - - /* - * Detach ourselves from the terminal, if required, - * and identify who is running us. - */ - -/* - syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d", - VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid); -*/ - - - for (;;) { -#if 0 /* FIXME: how do we synchonize? */ - -/* !!! here should be done some kind of synchronization - I did it following way ... */ -/* GlobalSystemStatus is set of different things shared between different tasks ... */ -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus * volatile stat; - stat=LockSTBSystemParam(); - stat->ConnectionStatus = NotConnected; - UnlockSTBSystemParam(); -#endif - - - while (1) { - rtems_event_set events; - int status; - -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - status=stat->WantConnection; - UnlockSTBSystemParam(); - - if (status == Connect) break; -#endif - rtems_event_receive(RTEMS_EVENT_1, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events); - } -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); -/* stat->WantConnection=DontConnect; */ - stat->ConnectionStatus = Connecting; - -/* Here you can change default nameserver ... */ - rtems_bsdnet_nameserver[0].s_addr=inet_addr(stat->DNS); - rtems_bsdnet_nameserver_count=1; - UnlockSTBSystemParam(); -#endif -/* initialize DNS services here */ - SetStatusInfo(0, "Connecting...",0); - - __res_init(); -#endif /* FIXME */ - /* - * 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; - } - - hungup = 0; - kill_link = 0; - - /* - * Do the equivalent of `mesg n' to stop broadcast messages. - */ - tty_mode = statbuf.st_mode; - - /* run connection script */ - /* - * 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 */ - setdtr(ttyfd, FALSE); - sleep(1); - setdtr(ttyfd, TRUE); - { -/* Make a call ... */ -#if 0 -/* XXX PPPConfiguration */ - char t[100]; - stat=LockSTBSystemParam(); - sprintf(t,"Calling the number %s ...",stat->Phone_Number); - UnlockSTBSystemParam(); - SetStatusInfo(0, t,0); -#endif - } - - - if ((i=connect_script(ttyfd)) >0) { -#if 0 -/* here go error messages ... */ - static char *error_msgs[]={ "Bad script", "IO Error" - "Timeout", "Busy", "No dialtone", "No carrier", - "No answer", "No answer from server" }; - setdtr(ttyfd, FALSE); - sprintf(t,"Communication error: %s",error_msgs[i-1]); - syslog(LOG_ERR, "Connect script failed"); - SetStatusInfo(0, t,1); -#endif - goto fail; - } - - else - if (i<0) - { -#if 0 - char t[100]; - sprintf(t,"Connecting the Internet at %d baud...",-i); - SetStatusInfo(0, t,0); -#endif - } - else - { -#if 0 - SetStatusInfo(0, "Connecting the Internet...",0); -#endif - } - syslog(LOG_INFO, "Serial connection established."); - - sleep(1); /* give it time to set up its terminal */ - - /* set line speed, flow control, etc.; clear CLOCAL if modem option */ - set_up_tty(ttyfd, 0); - - /* reopen tty if necessary to wait for carrier */ - - /* run welcome script, if any */ -/* if (welcomer && welcomer[0]) { - if (device_script(welcomer, 21, ttyfd) < 0) - syslog(LOG_WARNING, "Welcome script failed"); - } - */ - /* set up the serial device as a ppp interface */ - establish_ppp(ttyfd); - -/* syslog(LOG_INFO, "Using interface ppp%d", interfunit); */ - (void) sprintf(ifname, "ppp%d", interfunit); - - /* - * Start opening the connection and wait for - * incoming events (reply, timeout, etc.). - */ -/* syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); */ - - rtems_bsdnet_semaphore_obtain(); - - lcp_lowerup(0); - lcp_open(0); /* Start protocol */ - - rtems_bsdnet_semaphore_release(); -#if 0 - SetStatusInfo(0, "Internet connection established.",1); -#endif - for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD;) { -#if 0 - wait_input(timeleft(&timo)); -#endif - calltimeout(); - get_input(); -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - if (stat->WantConnection==DontConnect) { - stat->ConnectionStatus = NotConnected; - SetStatusInfo(0, "Disconnecting ...",0); - lcp_close(0, ""); - kill_link = 0; - } - UnlockSTBSystemParam(); -#endif - 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; - } - } - /* - * 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(); - disestablish_ppp(ttyfd); -#if 0 - SetStatusInfo(0, "Broken the internet connection.",1); -#endif - /* - * 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 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - stat->ConnectionStatus = NotConnected; - stat->WantConnection=DontConnect; - UnlockSTBSystemParam(); -#endif - if (ttyfd >= 0) - close_tty(); - - - - } - - return 0; -} - -/* - * detach - detach us from the controlling terminal. - */ -void detach() -{ -} - -/* - * 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) { -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus * volatile stat; -#endif -/* syslog(LOG_NOTICE, "Modem hangup"); */ - hungup = 1; -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - stat->ConnectionStatus = NotConnected; - UnlockSTBSystemParam(); -#endif - - lcp_lowerdown(0); /* serial link is no longer available */ - link_terminated(0); - return; - } -/* if ((debug)) - log_packet(p, len, "rcvd ", LOG_DEBUG); -*/ - - if (len < PPP_HDRLEN) { -/* - if (debug) - MAINDEBUG((LOG_INFO, "io(): Received short packet.")); -*/ - return; - } -/* We need to modify internal network structures here */ - rtems_bsdnet_semaphore_obtain(); - - 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.")); - rtems_bsdnet_semaphore_release(); - 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)) { - - rtems_bsdnet_semaphore_release(); - 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); - rtems_bsdnet_semaphore_release(); - return; - } - if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag - && protp->datainput != NULL) { - (*protp->datainput) (0, p, len); - rtems_bsdnet_semaphore_release(); - return; - } - } - - lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); - rtems_bsdnet_semaphore_release(); -} - - -/* - * 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(); -} - -/* - * cleanup - restore anything which needs to be restored before we exit - */ -/* ARGSUSED */ -static void cleanup() -{ - sys_cleanup(); - - if (ttyfd >= 0) - close_tty(); - -} - -/* - * close_tty - restore the terminal device and close it. - */ -static void close_tty() -{ - disestablish_ppp(ttyfd); - - /* drop dtr to hang up */ - 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); - close(ttyfd); - ttyfd = -1; -} - - -struct callout { - struct timeval c_time; - void *c_arg; - void (*c_func) __P((void *)); - struct callout *c_next; -}; - -static struct callout *callout = NULL; -static struct timeval timenow; - -/* - * timeout - Schedule a timeout. - * - * Note that this timeout takes the number of seconds, NOT hz (as in - * the kernel). - */ -void my_timeout(func, arg, time) -void (*func) __P((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) __P((void *)); -void *arg; -{ - struct callout **copp, *freep; - - MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); - - 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) { - 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; -} - - -/* - * term - Catch SIGTERM signal and SIGINT signal (^C/del). - * - * Indicates that we should initiate a graceful disconnect and exit. - */ -static void term(sig) -int sig; -{ - /* persist = 0; *//* don't try to restart */ - kill_link = 1; -} - -int modem_fd; /* FIXME: should not be global... */ -int connect_script(int fd) -{ -#if 0 /* FIXME: This is WinNT special */ - char program[256] = "TIMEOUT@10@@CLIENT@CLIENTSERVER"; -#else - char program[256] = { 0 }; -#endif -#if 0 -/* XXX PPPConfiguration */ - GlobalSystemStatus * volatile stat; -#endif -#if 0 -/* Connect scripts are almost the same as in Linux Chat ... */ - static char *scripts[] = - { - "TIMEOUT@5@@\rAT@OK-+++\\c-OK@ATH0@TIMEOUT@90@OK@ATDT%s@CONNECT@", - "TIMEOUT@5@@\rAT@OK-+++\\c-OK@ATH0@TIMEOUT@90@OK@ATDT%s@CONNECT@@ppp@@Username:@%s@Password:@%s@" - }; -#endif - modem_fd = fd; -#if 0 -/* XXX PPPConfiguration */ - stat=LockSTBSystemParam(); - if (strcmp("",stat->PPP_User)) - { - stat->provider=Poland_TPSA; - } - else - stat->provider=DumbLogin; - switch (stat->provider) { - case Poland_TPSA: /* TPSA - Polish Telecom */ - sprintf(program, scripts[1], stat->Phone_Number, stat->PPP_User, stat->PPP_Password); - break; - default: - sprintf(program, scripts[0], stat->Phone_Number); - - } - UnlockSTBSystemParam(); -#endif - conn_running = 0; - - return chatmain(program); -} - - -/* - * 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; -{ - - return 0; -} - - -/* - * reap_kids - get status from any dead child processes, - * and log a message for abnormal terminations. - */ -static void reap_kids() -{ -} - - -/* - * log_packet - format a packet and log it. - */ - -char line[256]; -char *linep; - -/*#define log_packet(p, len, prefix, level) */ -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. - */ -/*#define format_packet(p, len, printer, arg) */ - -void format_packet(p, len, printer, arg) -u_char *p; -int len; -void (*printer) __P((void *, char *,...)); -void *arg; -{ -/* - int i, n; - u_short proto; - 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); - } - */ -} - - - -/* XXX currently unused */ -#if 0 -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; -} -#endif - -/* - * print_string - print a readable representation of a string using - * printer. - */ -/*#define print_string(p, len, printer, arg) */ - -void print_string(p, len, printer, arg) -char *p; -int len; -void (*printer) __P((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) -/*#define vfmtmsg(buf, buflen, fmt, args) */ - -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 *); - #ifndef __powerpc__ - n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list)); - #else - - n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *)); - #endif - buf += n; - buflen -= n; - continue; - case 't': - break; - case 'v': - case 'q': - 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; - --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; - */ - return 0; -} - - -/* - * script_setenv - set an environment variable value to be used - * for scripts that we run (e.g. ip-up, auth-up, etc.) - */ -#define script_setenv(var, value) -/* - 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); - - 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; - } - - 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. - */ -#define script_unsetenv(var) -/* - 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/c/src/libnetworking/pppd/rtems-ppp.c b/c/src/libnetworking/pppd/rtems-ppp.c deleted file mode 100644 index 12ca0eb9fb..0000000000 --- a/c/src/libnetworking/pppd/rtems-ppp.c +++ /dev/null @@ -1,1521 +0,0 @@ -/* - * sys-bsd.c - System-dependent procedures for setting up - * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, RTEMS, 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[] = "$Id$"; */ -/* $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */ -#endif - -/* - * TODO: - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef NetBSD1_2 -#include -#endif -#ifdef PPP_FILTER -#include -#endif - -#include -#include -#include -#include -#include -#include - -#if RTM_VERSION >= 3 -#include -#if defined(NetBSD) && (NetBSD >= 199703) -#include -#else /* NetBSD 1.2D or later */ -#include -#endif -#endif - -#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 */ - -#if 0 -static char *lock_file; /* name of lock file created */ -#endif - -static int loop_slave = -1; -static int loop_master; -#if 0 -static char loop_name[20]; -#endif - -static unsigned char inbuf[512]; /* buffer for chars read from loopback */ - -static int sockfd; /* socket for doing interface ioctls */ - -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 __P((u_int32_t, int)); -static int get_ether_addr __P((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); - } -} - -/* - * 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() -{ - close(sockfd); - 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 any ppp interfaces - * (in fact we check whether we can do an ioctl on ppp0). - */ -int -ppp_available() -{ - int s, ok; - struct ifreq ifr; - extern char *no_ppp_msg; - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - return 1; /* can't tell */ - - strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); - ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; - close(s); - - no_ppp_msg = "\ -This system lacks kernel support for PPP. To include PPP support\n\ -in the kernel, please follow the steps detailed in the README.bsd\n\ -file in the ppp-2.2 distribution.\n"; - return ok; -} - -/* - * 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, &interfunit) < 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 != interfunit) { - syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d", - interfunit, 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. - */ -#define fcntl(a) - - -/* 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 != interfunit) { - syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d", - interfunit, 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; - tios.c_cc[VSTART] = 0x11; - } - - 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 = 9600;*/ -/* we hardcode it temporarily */ - if (tcsetattr(fd, TCSANOW, &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; - } -*/} - -/* - * - 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); -} - - -/* - * 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() -{ - -} - - -/* - * output - Output PPP packet. - */ -void -output(unit, p, len) - int unit; - u_char *p; - int len; -{ - if (debug); - syslog(LOG_DEBUG, "sent %d bytes ", len ); - - if (write(ttyfd, p, len) < 0) { -/* if (errno != EIO) - syslog(LOG_ERR, "write: %m"); -*/ } -} - -extern int rtems_bsdnet_microseconds_per_tick; -#include -#include -/* - * wait_input - wait until there is data available on ttyfd, - * for the length of time specified by *timo (indefinite - * if timo is NULL). - */ - -/* - * 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; -*/ - -/* 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; -{ - rtems_status_code status; - rtems_interval ticks; - - ticks = - (timo->tv_sec*1000000+timo->tv_usec)/rtems_bsdnet_microseconds_per_tick; - status = rtems_task_wake_after( ticks ); -} - - -/* - * 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 || errno == ETIMEDOUT) - return -1; - syslog(LOG_ERR, "read: %m"); - } - 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; -/* struct sockaddr_in address; - struct sockaddr_in netmask; - struct sockaddr_in broadcast; - - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - memset (&address, '\0', sizeof address); - address.sin_len = sizeof address; - address.sin_family = AF_INET; - address.sin_addr.s_addr = o; - memcpy (&ifr.ifr_addr, &address, sizeof address); - if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { - if (errno != EADDRNOTAVAIL) - syslog(LOG_WARNING, "Couldn't remove interface address: %m"); - } - - if (ioctl (sockfd, SIOCSIFADDR, &ifr) < 0) - syslog(LOG_ERR, "Can't set address: "); - - - memset (&netmask, '\0', sizeof netmask); - netmask.sin_len = sizeof netmask; - netmask.sin_family = AF_INET; - netmask.sin_addr.s_addr = m ; - memcpy (&ifr.ifr_addr, &netmask, sizeof netmask); - - if (ioctl (sockfd, SIOCSIFNETMASK, &ifr) < 0) - syslog(LOG_ERR,"Can't set netmask: "); - memset (&broadcast, '\0', sizeof broadcast); - broadcast.sin_len = sizeof broadcast; - broadcast.sin_family = AF_INET; - broadcast.sin_addr.s_addr = h; - memcpy (&ifr.ifr_broadaddr, &broadcast, sizeof broadcast); - if (ioctl (sockfd, SIOCSIFBRDADDR, &ifr) < 0) - syslog(LOG_ERR,"Can't set broadcast address: "); - -*/ - 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 sockaddr_in address; - struct sockaddr_in netmask; - /* struct sockaddr_in broadcast; */ - struct sockaddr_in gateway; - -/* 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((void *) &address, 0, sizeof(address)); - address.sin_len = sizeof address; - address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - - memset((void *) &netmask, 0, sizeof(netmask)); - netmask.sin_len = sizeof netmask; - netmask.sin_addr.s_addr = INADDR_ANY; - netmask.sin_family = AF_INET; - - - if (cmd=='s') - { - memset((void *) &gateway, 0, sizeof(gateway)); - gateway.sin_len = sizeof gateway; - gateway.sin_family = AF_INET; - gateway.sin_addr.s_addr = htons(g) ; - - - if (rtems_bsdnet_rtrequest (RTM_ADD, - (struct sockaddr *)&address, - (struct sockaddr *)&gateway, - (struct sockaddr *)&netmask, - (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) - /*syslog(LOG_WARNING,"Can't set default route: ")*/ - ; - } - else - { - memset((void *) &gateway, 0, sizeof(gateway)); - gateway.sin_len = sizeof gateway; - gateway.sin_family = AF_INET; - gateway.sin_addr.s_addr = INADDR_ANY; - - if (rtems_bsdnet_rtrequest (RTM_DELETE, - (struct sockaddr *)&address, - (struct sockaddr *)&gateway, - (struct sockaddr *)&netmask, - (RTF_UP | RTF_STATIC), NULL) < 0) - /*syslog(LOG_WARNING,"Can't set default route: ")*/ - ; - } - -/* - rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE; - rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY; - 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; - return 0; - - - /* - * 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 */ - - -/* - * get_ether_addr - get the hardware address of an interface on the - * the same subnet as ipaddr. - */ -#define MAX_IFS 32 - -static int -get_ether_addr(ipaddr, hwaddr) - u_int32_t ipaddr; - struct sockaddr_dl *hwaddr; -{ - struct ifreq *ifr, *ifend, *ifp; - u_int32_t ina, mask; - struct sockaddr_dl *dla; - struct ifreq ifreq; - struct ifconf ifc; - struct ifreq ifs[MAX_IFS]; - - ifc.ifc_len = sizeof(ifs); - ifc.ifc_req = ifs; - if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { - syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m"); - return 0; - } - - /* - * Scan through looking for an interface with an Internet - * address on the same subnet as `ipaddr'. - */ - ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); - for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) - ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { - if (ifr->ifr_addr.sa_family == AF_INET) { - ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; - strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); - /* - * Check that the interface is up, and not point-to-point - * or loopback. - */ - if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) - continue; - if ((ifreq.ifr_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. - */ - if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) - continue; - mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; - if ((ipaddr & mask) != (ina & mask)) - continue; - - break; - } - } - - if (ifr >= ifend) - return 0; - syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name); - - /* - * Now scan through again looking for a link-level address - * for this interface. - */ - ifp = ifr; - for (ifr = ifc.ifc_req; ifr < ifend; ) { - if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 - && ifr->ifr_addr.sa_family == AF_LINK) { - /* - * Found the link-level address - copy it out - */ - dla = (struct sockaddr_dl *) &ifr->ifr_addr; - BCOPY(dla, hwaddr, dla->sdl_len); - return 1; - } - ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); - } - - 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 ifreq *ifr, *ifend, ifreq; - struct ifconf ifc; - struct ifreq ifs[MAX_IFS]; - - 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. - */ - ifc.ifc_len = sizeof(ifs); - ifc.ifc_req = ifs; - if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { - syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m"); - return mask; - } - ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); - for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) - ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { - /* - * Check the interface's internet address. - */ - if (ifr->ifr_addr.sa_family != AF_INET) - continue; - ina = ((struct sockaddr_in *) &ifr->ifr_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. - */ - strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) - continue; - if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) - != IFF_UP) - continue; - /* - * Get its netmask and OR it into our mask. - */ - if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) - continue; - mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr; - } - - return mask; -} - -/* - * Use the hostid as part of the random number seed. - */ -int -get_host_seed() -{ - return 33; -/* 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) { - - 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) { - - 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/c/src/libnetworking/pppd/rtemsmain.c b/c/src/libnetworking/pppd/rtemsmain.c new file mode 100644 index 0000000000..5a266a9ff3 --- /dev/null +++ b/c/src/libnetworking/pppd/rtemsmain.c @@ -0,0 +1,903 @@ +/* + * 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. + */ + +#define RCSID "$Id$" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +extern void rtems_bsdnet_semaphore_obtain(void); +extern void rtems_bsdnet_semaphore_release(void); +extern int chatmain(char *argv); + +#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 + +#ifdef IPX_CHANGE +#include "ipxcp.h" +#endif /* IPX_CHANGE */ +#ifdef AT_CHANGE +#include "atcp.h" +#endif + +static const char rcsid[] = RCSID; + +/* interface vars */ +char ifname[32]; /* Interface name */ +int pppifunit; /* Interface unit number */ + +char *progname; /* Name of this program */ +char hostname[MAXNAMELEN]; /* Our hostname */ +static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */ + +int ttyfd; /* Serial port file descriptor */ +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 */ +struct stat devstat; /* result of stat() on devnam */ +int prepass = 0; /* doing prepass to find device name */ +int devnam_fixed; /* set while in options.ttyxx file */ +volatile int status; /* exit status for pppd */ +int unsuccess; /* # unsuccessful connection attempts */ +int do_callback; /* != 0 if we should do callback next */ +int doing_callback; /* != 0 if we are doing callback */ +char *callback_script; /* script for doing callback */ + +int (*holdoff_hook) __P((void)) = NULL; +int (*new_phase_hook) __P((int)) = NULL; + +static int fd_ppp = -1; /* fd for talking PPP */ +static int pty_master; /* fd for master side of pty */ +static int pty_slave; /* fd for slave side of pty */ +static int real_ttyfd; /* fd for actual serial port (not pty) */ + +int phase; /* where the link is at */ +int kill_link; +int open_ccp_flag; + +static int waiting; + +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 */ + +char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n"; + +static struct timeval start_time; /* Time when link was started. */ + +struct pppd_stats link_stats; +int link_connect_time; +int link_stats_valid; + +/* Prototypes for procedures local to this file. */ + +static void cleanup __P((void)); +static void close_tty __P((void)); +static void get_input __P((void)); +static void calltimeout __P((void)); +static struct timeval *timeleft __P((struct timeval *)); +static void holdoff_end __P((void *)); +static int device_script __P((char *, int, int, int)); + +extern char *ttyname __P((int)); +extern char *getlogin __P((void)); +int pppdmain __P((int, char *[])); + +/* + * 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 +pppdmain(argc, argv) + int argc; + char *argv[]; +{ + int i, fdflags, t; + char *connector; + struct timeval timo; + struct protent *protp; + + new_phase(PHASE_INITIALIZE); + + script_env = NULL; + hostname[MAXNAMELEN-1] = 0; + privileged = 1; + privileged_option = 1; + + /* + * Initialize magic number generator now so that protocols may + * use magic numbers in initialization. + */ + magic_init(); + +#ifdef XXX_XXX + /* moved code the the rtems_pppd_reset_options function */ + + /* + * 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); +#endif + + progname = *argv; + + + if (!ppp_available()) { + option_error(no_ppp_msg); + return(EXIT_NO_KERNEL_SUPPORT); + } + + /* + * Check that the options given are valid and consistent. + */ + if (!sys_check_options()) { + return(EXIT_OPTION_ERROR); + } + if (!auth_check_options()) { + return(EXIT_OPTION_ERROR); + } + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->check_options != NULL) + (*protp->check_options)(); + + /* default holdoff to 0 if no connect script has been given */ + if (connect_script == 0 && !holdoff_specified) + holdoff = 0; + + if (default_device) + nodetach = 1; + + /* + * Initialize system-dependent stuff. + */ + sys_init(); + /* if (debug) + setlogmask(LOG_UPTO(LOG_DEBUG)); + */ + + waiting = 0; + + do_callback = 0; + for (;;) { + + need_holdoff = 1; + ttyfd = -1; + real_ttyfd = -1; + status = EXIT_OK; + ++unsuccess; + doing_callback = do_callback; + do_callback = 0; + + new_phase(PHASE_SERIALCONN); + + /* + * Get a pty master/slave pair if the pty, notty, or record + * options were specified. + */ + strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); + pty_master = -1; + pty_slave = -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. + */ + hungup = 0; + kill_link = 0; + connector = doing_callback? callback_script: connect_script; + if (devnam[0] != 0) { + for (;;) { + /* If the user specified the device name, become the + user before opening it. */ + int err; + ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0); + err = errno; + if (ttyfd >= 0) { + break; + } + errno = err; + if (err != EINTR) { + error("Failed to open %s: %m", devnam); + status = EXIT_OPEN_FAILED; + } + if (!persist || err != EINTR) + goto fail; + } + if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 + || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) + warn("Couldn't reset non-blocking mode on device: %m"); + + /* + * Set line speed, flow control, etc. + * If we have a non-null connection or initializer script, + * 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 could clear CLOCAL at this point. + */ + set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0) + || initializer != NULL)); + real_ttyfd = ttyfd; + } + + /* run connection script */ + if ((connector && connector[0]) || initializer) { + if (real_ttyfd != -1) { + /* XXX do this if doing_callback == CALLBACK_DIALIN? */ + if (!default_device && modem) { + setdtr(real_ttyfd, 0); /* in case modem is off hook */ + sleep(1); + setdtr(real_ttyfd, 1); + } + } + + if (initializer && initializer[0]) { + if (device_script(initializer, ttyfd, ttyfd, 0) < 0) { + error("Initializer script failed"); + status = EXIT_INIT_FAILED; + goto fail; + } + if (kill_link) + goto disconnect; + + info("Serial port initialized."); + } + + if (connector && connector[0]) { + if (device_script(connector, ttyfd, ttyfd, 0) < 0) { + error("Connect script failed"); + status = EXIT_CONNECT_FAILED; + goto fail; + } + if (kill_link) + goto disconnect; + + info("Serial connection established."); + } + + /* set line speed, flow control, etc.; + clear CLOCAL if modem option */ + if (real_ttyfd != -1) + set_up_tty(real_ttyfd, 0); + + if (doing_callback == CALLBACK_DIALIN) + connector = NULL; + } + + /* reopen tty if necessary to wait for carrier */ + if (connector == NULL && modem && devnam[0] != 0) { + for (;;) { + if ((i = open(devnam, O_RDWR)) >= 0) + break; + if (errno != EINTR) { + error("Failed to reopen %s: %m", devnam); + status = EXIT_OPEN_FAILED; + } + if (!persist || errno != EINTR || hungup || kill_link) + goto fail; + } + close(i); + } + + info("Serial connection established."); + sleep(1); + + /* run welcome script, if any */ + if (welcomer && welcomer[0]) { + if (device_script(welcomer, ttyfd, ttyfd, 0) < 0) + warn("Welcome script failed"); + } + + /* set up the serial device as a ppp interface */ + fd_ppp = establish_ppp(ttyfd); + if (fd_ppp < 0) { + status = EXIT_FATAL_ERROR; + goto disconnect; + } + + if (!demand) { + info("Using interface ppp%d", pppifunit); + slprintf(ifname, sizeof(ifname), "ppp%d", pppifunit); + } + + /* + * Start opening the connection and wait for + * incoming events (reply, timeout, etc.). + */ + notice("Connect: %s <--> %s", ifname, ppp_devnam); + gettimeofday(&start_time, NULL); + + rtems_bsdnet_semaphore_obtain(); + lcp_lowerup(0); + lcp_open(0); /* Start protocol */ + rtems_bsdnet_semaphore_release(); + + open_ccp_flag = 0; + status = EXIT_NEGOTIATION_FAILED; + new_phase(PHASE_ESTABLISH); + while (phase != PHASE_DEAD) { + waiting = 1; + wait_input(timeleft(&timo)); + waiting = 0; + + calltimeout(); + get_input(); + if (kill_link) { + lcp_close(0, "User request"); + kill_link = 0; + } + if (open_ccp_flag) { + if (phase == PHASE_NETWORK || phase == PHASE_RUNNING) { + ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ + (*ccp_protent.open)(0); + } + open_ccp_flag = 0; + } + } + + /* + * 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); + fd_ppp = -1; + if (!hungup) + lcp_lowerdown(0); + + /* + * Run disconnector script, if requested. + * XXX we may not be able to do this if the line has hung up! + */ + disconnect: + if (disconnect_script && !hungup) { + new_phase(PHASE_DISCONNECT); + if (real_ttyfd >= 0) + set_up_tty(real_ttyfd, 1); + if (device_script(disconnect_script, ttyfd, ttyfd, 0) < 0) { + warn("disconnect script failed"); + } else { + info("Serial link disconnected."); + } + } + + fail: + if (pty_master >= 0) + close(pty_master); + if (pty_slave >= 0) + close(pty_slave); + if (real_ttyfd >= 0) + close_tty(); + + if (!persist || (maxfail > 0 && unsuccess >= maxfail)) + break; + + kill_link = 0; + if (demand) + demand_discard(); + t = need_holdoff? holdoff: 0; + if (holdoff_hook) + t = (*holdoff_hook)(); + if (t > 0) { + new_phase(PHASE_HOLDOFF); + TIMEOUT(holdoff_end, NULL, t); + do { + waiting = 1; + wait_input(timeleft(&timo)); + waiting = 0; + + calltimeout(); + if (kill_link) { + kill_link = 0; + new_phase(PHASE_DORMANT); /* allow signal to end holdoff */ + } + } while (phase == PHASE_HOLDOFF); + if (!persist) + break; + } + } + + die(status); + return 0; +} + +/* + * holdoff_end - called via a timeout when the holdoff period ends. + */ +static void +holdoff_end(arg) + void *arg; +{ + new_phase(PHASE_DORMANT); +} + +/* List of protocol names, to make our messages a little more informative. */ +struct protocol_list { + u_short proto; + const char *name; +} protocol_list[] = { + { 0x21, "IP" }, + { 0x23, "OSI Network Layer" }, + { 0x25, "Xerox NS IDP" }, + { 0x27, "DECnet Phase IV" }, + { 0x29, "Appletalk" }, + { 0x2b, "Novell IPX" }, + { 0x2d, "VJ compressed TCP/IP" }, + { 0x2f, "VJ uncompressed TCP/IP" }, + { 0x31, "Bridging PDU" }, + { 0x33, "Stream Protocol ST-II" }, + { 0x35, "Banyan Vines" }, + { 0x39, "AppleTalk EDDP" }, + { 0x3b, "AppleTalk SmartBuffered" }, + { 0x3d, "Multi-Link" }, + { 0x3f, "NETBIOS Framing" }, + { 0x41, "Cisco Systems" }, + { 0x43, "Ascom Timeplex" }, + { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, + { 0x47, "DCA Remote Lan" }, + { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, + { 0x4b, "SNA over 802.2" }, + { 0x4d, "SNA" }, + { 0x4f, "IP6 Header Compression" }, + { 0x6f, "Stampede Bridging" }, + { 0xfb, "single-link compression" }, + { 0xfd, "1st choice compression" }, + { 0x0201, "802.1d Hello Packets" }, + { 0x0203, "IBM Source Routing BPDU" }, + { 0x0205, "DEC LANBridge100 Spanning Tree" }, + { 0x0231, "Luxcom" }, + { 0x0233, "Sigma Network Systems" }, + { 0x8021, "Internet Protocol Control Protocol" }, + { 0x8023, "OSI Network Layer Control Protocol" }, + { 0x8025, "Xerox NS IDP Control Protocol" }, + { 0x8027, "DECnet Phase IV Control Protocol" }, + { 0x8029, "Appletalk Control Protocol" }, + { 0x802b, "Novell IPX Control Protocol" }, + { 0x8031, "Bridging NCP" }, + { 0x8033, "Stream Protocol Control Protocol" }, + { 0x8035, "Banyan Vines Control Protocol" }, + { 0x803d, "Multi-Link Control Protocol" }, + { 0x803f, "NETBIOS Framing Control Protocol" }, + { 0x8041, "Cisco Systems Control Protocol" }, + { 0x8043, "Ascom Timeplex" }, + { 0x8045, "Fujitsu LBLB Control Protocol" }, + { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, + { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, + { 0x804b, "SNA over 802.2 Control Protocol" }, + { 0x804d, "SNA Control Protocol" }, + { 0x804f, "IP6 Header Compression Control Protocol" }, + { 0x006f, "Stampede Bridging Control Protocol" }, + { 0x80fb, "Single Link Compression Control Protocol" }, + { 0x80fd, "Compression Control Protocol" }, + { 0xc021, "Link Control Protocol" }, + { 0xc023, "Password Authentication Protocol" }, + { 0xc025, "Link Quality Report" }, + { 0xc027, "Shiva Password Authentication Protocol" }, + { 0xc029, "CallBack Control Protocol (CBCP)" }, + { 0xc081, "Container Control Protocol" }, + { 0xc223, "Challenge Handshake Authentication Protocol" }, + { 0xc281, "Proprietary Authentication Protocol" }, + { 0, NULL }, +}; + +/* + * protocol_name - find a name for a PPP protocol. + */ +const char * +protocol_name(proto) + int proto; +{ + struct protocol_list *lp; + + for (lp = protocol_list; lp->proto != 0; ++lp) + if (proto == lp->proto) + return lp->name; + return NULL; +} + +/* + * 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) { + notice("Modem hangup"); + hungup = 1; + status = EXIT_HANGUP; + lcp_lowerdown(0); /* serial link is no longer available */ + link_terminated(0); + return; + } + + if (debug /*&& (debugflags & DBG_INPACKET)*/) + dbglog("rcvd %P", p, len); + + if (len < PPP_HDRLEN) { + MAINDEBUG(("io(): Received short packet.")); + return; + } + + rtems_bsdnet_semaphore_obtain(); + 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(("get_input: Received non-LCP packet when LCP not open.")); + rtems_bsdnet_semaphore_release(); + 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(("get_input: discarding proto 0x%x in phase %d", + protocol, phase)); + rtems_bsdnet_semaphore_release(); + 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); + rtems_bsdnet_semaphore_release(); + return; + } + if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag + && protp->datainput != NULL) { + (*protp->datainput)(0, p, len); + rtems_bsdnet_semaphore_release(); + return; + } + } + + if (debug) { + const char *pname = protocol_name(protocol); + if (pname != NULL) + warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); + else + warn("Unsupported protocol 0x%x received", protocol); + } + lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); + rtems_bsdnet_semaphore_release(); +} + +/* + * new_phase - signal the start of a new phase of pppd's operation. + */ +void +new_phase(p) + int p; +{ + phase = p; + if (new_phase_hook) + (*new_phase_hook)(p); +} + +/* + * die - clean up state and exit with the specified status. + */ +void +die(status) + int status; +{ + cleanup(); +} + +/* + * cleanup - restore anything which needs to be restored before we exit + */ +/* ARGSUSED */ +static void +cleanup() +{ + sys_cleanup(); + + if (fd_ppp >= 0) + disestablish_ppp(ttyfd); + if (real_ttyfd >= 0) + close_tty(); + + sys_close(); +} + +/* + * close_tty - restore the terminal device and close it. + */ +static void +close_tty() +{ + /* drop dtr to hang up */ + if (!default_device && modem) { + setdtr(real_ttyfd, 0); + /* + * 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(real_ttyfd); + + close(real_ttyfd); + real_ttyfd = -1; +} + +/* + * update_link_stats - get stats at link termination. + */ +void +update_link_stats(u) + int u; +{ + struct timeval now; + char numbuf[32]; + + if (!get_ppp_stats(u, &link_stats) + || gettimeofday(&now, NULL) < 0) + return; + link_connect_time = now.tv_sec - start_time.tv_sec; + link_stats_valid = 1; + + slprintf(numbuf, sizeof(numbuf), "%d", link_connect_time); + slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_out); + slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_in); +} + +struct callout { + struct timeval c_time; /* time at which to call routine */ + void *c_arg; /* argument to routine */ + void (*c_func) __P((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 +ppptimeout(func, arg, time) + void (*func) __P((void *)); + void *arg; + int time; +{ + struct callout *newp, *p, **pp; + + MAINDEBUG(("Timeout %p:%p in %d seconds.", func, arg, time)); + + /* + * Allocate timeout. + */ + if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) + fatal("Out of memory in timeout()!"); + 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_usec)) + break; + newp->c_next = p; + *pp = newp; +} + + +/* + * untimeout - Unschedule a timeout. + */ +void +untimeout(func, arg) + void (*func) __P((void *)); + void *arg; +{ + struct callout **copp, *freep; + + MAINDEBUG(("Untimeout %p:%p.", func, 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; + 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) + fatal("Failed to get time of day: %m"); + 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; +} + +/* + * device_script - run a program to talk to the serial device + * (e.g. to run the connector or disconnector script). + */ +static int +device_script(program, in, out, dont_wait) + char *program; + int in, out; + int dont_wait; +{ + char pScript[256]; + + strcpy(pScript, program); + return chatmain(pScript); +} + +/* + * novm - log an error message saying we ran out of memory, and die. + */ +void +novm(msg) + char *msg; +{ + fatal("Virtual memory exhausted allocating %s\n", msg); +} diff --git a/c/src/libnetworking/pppd/rtemspppd.c b/c/src/libnetworking/pppd/rtemspppd.c new file mode 100644 index 0000000000..5a821cdfaf --- /dev/null +++ b/c/src/libnetworking/pppd/rtemspppd.c @@ -0,0 +1,173 @@ + +#include +#include "pppd.h" +#include "rtemspppd.h" + + +/* define pppd function prototypes */ +extern void pppasyncattach(void); +extern int pppdmain(int, char **); + +/* define global variables */ +rtems_id rtems_pppd_taskid; + + +static rtems_task pppTask(rtems_task_argument arg) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_option options; + rtems_event_set in; + rtems_event_set out; + + /* call function to setup ppp line discipline */ + pppasyncattach(); + + /* enter processing loop */ + in = (RTEMS_EVENT_29 | RTEMS_EVENT_30); + options = (RTEMS_EVENT_ANY | RTEMS_WAIT); + while ( sc == RTEMS_SUCCESSFUL ) { + /* wait for the next event */ + sc = rtems_event_receive(in, options, RTEMS_NO_TIMEOUT, &out); + if ( sc == RTEMS_SUCCESSFUL ) { + /* determine which event was sent */ + if ( out & RTEMS_EVENT_29 ) { + /* terminate event received */ + /* set value to break out of event loop */ + sc = RTEMS_UNSATISFIED; + } + else if ( out & RTEMS_EVENT_30 ) { + /* connect request */ + /* execute the pppd main code */ + pppdmain(0, NULL); + } + } + } + + /* terminate myself */ + rtems_task_delete(RTEMS_SELF); +} + +int rtems_pppd_initialize(void) +{ + int iReturn = (int)-1; + rtems_status_code status; + rtems_name taskName; + + taskName = rtems_build_name( 'p', 'p', 'p', 'd' ); + status = rtems_task_create(taskName, + RTEMS_PPPD_TASK_PRIORITY, + RTEMS_PPPD_TASK_STACK_SIZE, + RTEMS_PPPD_TASK_INITIAL_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &rtems_pppd_taskid); + if ( status == RTEMS_SUCCESSFUL ) { + status = rtems_task_start(rtems_pppd_taskid, pppTask, 0); + if ( status == RTEMS_SUCCESSFUL ) { + iReturn = rtems_pppd_reset_options(); + } + } + + return ( iReturn ); +} + +int rtems_pppd_terminate(void) +{ + /* send terminate signal to pppd task */ + rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_29); + + /* call the disconnect function */ + rtems_pppd_disconnect(); + + return ( 0 ); +} + +int rtems_pppd_reset_options(void) +{ + int i; + struct protent *protp; + + /* + * 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); + + return ( 0 ); +} + +int rtems_pppd_set_hook(int id, rtems_pppd_hookfunction hookfp) +{ + int iReturn = (int)0; + + switch ( id ) { + case RTEMS_PPPD_LINKUP_HOOK: + auth_linkup_hook = hookfp; + break; + case RTEMS_PPPD_LINKDOWN_HOOK: + auth_linkdown_hook = hookfp; + break; + case RTEMS_PPPD_IPUP_HOOK: + ip_up_hook = hookfp; + break; + case RTEMS_PPPD_IPDOWN_HOOK: + ip_down_hook = hookfp; + break; + default: + iReturn = (int)-1; + break; + } + + return ( iReturn ); +} + +int rtems_pppd_set_option(const char *pOption, const char *pValue) +{ + int iReturn = (int)0; + int prevPhase; + struct wordlist option; + struct wordlist value; + + if ( pOption != (const char *)0 ) { + /* initialize the values */ + option.word = (char *)pOption; + option.next = (struct wordlist *)0; + if ( pValue != (const char *)0 ) { + option.next = &value; + value.word = (char *)pValue; + value.next = (struct wordlist *)0; + } + + /* save current phase value */ + prevPhase = phase; + phase = PHASE_INITIALIZE; + + /* process option and reset phase value */ + iReturn = options_from_list(&option, 1); + phase = prevPhase; + } + + return ( iReturn ); +} + +int rtems_pppd_connect(void) +{ + /* send connect signal to pppd task */ + rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_30); + + return ( 0 ); +} + +int rtems_pppd_disconnect(void) +{ + /* set pppd global variables to disconnect */ + persist = 0; + kill_link = 1; + + /* send event to wake up the pppd code */ + /* pretend its a serial interrput */ + rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_31); + + return ( 0 ); +} diff --git a/c/src/libnetworking/pppd/rtemspppd.h b/c/src/libnetworking/pppd/rtemspppd.h new file mode 100644 index 0000000000..9d44e58594 --- /dev/null +++ b/c/src/libnetworking/pppd/rtemspppd.h @@ -0,0 +1,38 @@ + +#ifndef RTEMSPPPD_H +#define RTEMSPPPD_H + +/* check to see if pppd task values are set */ +#ifndef RTEMS_PPPD_TASK_PRIORITY +#define RTEMS_PPPD_TASK_PRIORITY 120 +#endif +#ifndef RTEMS_PPPD_TASK_STACK_SIZE +#define RTEMS_PPPD_TASK_STACK_SIZE (10*1024) +#endif +#ifndef RTEMS_PPPD_TASK_INITIAL_MODES +#define RTEMS_PPPD_TASK_INITIAL_MODES (RTEMS_PREEMPT | \ + RTEMS_NO_TIMESLICE | \ + RTEMS_NO_ASR | \ + RTEMS_INTERRUPT_LEVEL(0)) +#endif + +/* define hook function identifiers */ +#define RTEMS_PPPD_LINKUP_HOOK 1 +#define RTEMS_PPPD_LINKDOWN_HOOK 2 +#define RTEMS_PPPD_IPUP_HOOK 3 +#define RTEMS_PPPD_IPDOWN_HOOK 4 + +/* define hook function pointer prototype */ +typedef void (*rtems_pppd_hookfunction)(void); + + +/* define pppd function prototyes */ +int rtems_pppd_initialize(void); +int rtems_pppd_terminate(void); +int rtems_pppd_reset_options(void); +int rtems_pppd_set_hook(int id, rtems_pppd_hookfunction hookfp); +int rtems_pppd_set_option(const char *pOption, const char *pValue); +int rtems_pppd_connect(void); +int rtems_pppd_disconnect(void); + +#endif diff --git a/c/src/libnetworking/pppd/sys-rtems.c b/c/src/libnetworking/pppd/sys-rtems.c new file mode 100644 index 0000000000..bfc80d50a6 --- /dev/null +++ b/c/src/libnetworking/pppd/sys-rtems.c @@ -0,0 +1,1322 @@ +/* + * 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. + */ + +#define RCSID "$Id$" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef PPP_FILTER +#include +#endif + +#include +#include +#include +#include +#include +#include + +#if RTM_VERSION >= 3 +#include +#if defined(NetBSD) && (NetBSD >= 199703) +#include +#else /* NetBSD 1.2D or later */ +#include +#endif +#endif + +#include +#include +#include +extern int rtems_bsdnet_microseconds_per_tick; +extern rtems_id rtems_pppd_taskid; + +#include "pppd.h" +#include "fsm.h" +#include "ipcp.h" + +static const char rcsid[] = RCSID; + + +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 int loop_slave = -1; +static int loop_master; + +static unsigned char inbuf[512]; /* buffer for chars read from loopback */ + +static int sockfd; /* socket for doing interface ioctls */ + +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 __P((u_int32_t, int)); +static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *)); + + +void +sys_serialcallback(struct termios *tty, void *arg) +{ + rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_31); +} + +/* + * 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) + fatal("Couldn't create IP socket: %m"); +} + +/* + * 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) { + strlcpy(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() +{ + close(sockfd); + if (loop_slave >= 0) { + close(loop_slave); + close(loop_master); + } +} + +/* + * sys_check_options - check the options that the user specified + */ +int +sys_check_options() +{ + return 1; +} + +/* + * ppp_available - check whether the system has any ppp interfaces + * (in fact we check whether we can do an ioctl on ppp0). + */ +int +ppp_available() +{ + int s, ok; + struct ifreq ifr; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return 1; /* can't tell */ + + strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); + ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; + close(s); + + return ok; +} + +/* + * establish_ppp - Turn the serial port into a ppp interface. + */ +int +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) + fatal("ioctl(transfer ppp unit): %m"); + } + + /* + * Save the old line discipline of fd, and set it to PPP. + */ + if (ioctl(fd, TIOCGETD, &initdisc) < 0) + fatal("ioctl(TIOCGETD): %m"); + if (ioctl(fd, TIOCSETD, &pppdisc) < 0) + fatal("ioctl(TIOCSETD): %m"); + + if (!demand) { + /* + * Find out which interface we were given. + */ + if (ioctl(fd, PPPIOCGUNIT, &pppifunit) < 0) + fatal("ioctl(PPPIOCGUNIT): %m"); + } else { + /* + * Check that we got the same unit again. + */ + if (ioctl(fd, PPPIOCGUNIT, &x) < 0) + fatal("ioctl(PPPIOCGUNIT): %m"); + if (x != pppifunit) + fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x); + 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) { + warn("ioctl (PPPIOCGFLAGS): %m"); + } else { + x |= (kdebugflag & 0xFF) * SC_DEBUG; + if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) + warn("ioctl(PPPIOCSFLAGS): %m"); + } + } + + /* + * Set device for non-blocking reads. + */ + if ((initfdflags = fcntl(fd, F_GETFL)) == -1 + || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) { + warn("Couldn't set device to non-blocking mode: %m"); + } + + return fd; +} + +/* + * 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) + fatal("ioctl(transfer ppp unit): %m"); + x = PPPDISC; + if (ioctl(loop_slave, TIOCSETD, &x) < 0) + fatal("ioctl(TIOCSETD): %m"); + + /* + * Check that we got the same unit again. + */ + if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) + fatal("ioctl(PPPIOCGUNIT): %m"); + if (x != pppifunit) + fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x); + 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) + warn("Couldn't restore device fd flags: %m"); + initfdflags = -1; + + /* Restore old line discipline. */ + if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0) + error("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) { + warn("Serial link is not 8-bit clean:"); + warn("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; + struct ttywakeup wakeup; + + if (tcgetattr(fd, &tios) < 0) + fatal("tcgetattr: %m"); + + if (!restore_term) { + inittermios = tios; + ioctl(fd, TIOCGWINSZ, &wsinfo); + } + + tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); + if (crtscts > 0 && !local) { + if (crtscts == 2) { +#ifdef CDTRCTS + tios.c_cflag |= CDTRCTS; +#endif + } else + tios.c_cflag |= CRTSCTS; + } else if (crtscts < 0) { + tios.c_cflag &= ~CRTSCTS; +#ifdef CDTRCTS + tios.c_cflag &= ~CDTRCTS; +#endif + } + + 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) + fatal("Baud rate for %s is 0; need explicit baud rate", devnam); + } + baud_rate = inspeed; + +/* if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { */ + if (tcsetattr(fd, TCSADRAIN, &tios) < 0) { + fatal("tcsetattr: %m"); + } + + /* set up callback function */ + wakeup.sw_pfn = sys_serialcallback; + wakeup.sw_arg = (void *)fd; + ioctl(fd, RTEMS_IO_RCVWAKEUP, &wakeup); + + 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 (tcsetattr(fd, TCSADRAIN, &inittermios) < 0) { + if (errno != ENXIO) + warn("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); +} + +/* + * get_pty - get a pty master/slave pair and chown the slave side + * to the uid given. Assumes slave_name points to >= 12 bytes of space. + */ +int +get_pty(master_fdp, slave_fdp, slave_name, uid) + int *master_fdp; + int *slave_fdp; + char *slave_name; + int uid; +{ + return 1; +} + + +/* + * 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. + */ +int +open_ppp_loopback() +{ + return loop_master; +} + + +/* + * output - Output PPP packet. + */ +void +output(unit, p, len) + int unit; + u_char *p; + int len; +{ + if (debug); + dbglog("sent %P", p, len); + + if (write(ttyfd, p, len) < 0) { + if (errno != EIO) + error("write: %m"); + } +} + + +/* + * wait_input - wait until there is data available, + * for the length of time specified by *timo (indefinite + * if timo is NULL). + */ +void +wait_input(timo) + struct timeval *timo; +{ + rtems_interval ticks; + rtems_event_set events; + + ticks = ((timo->tv_sec*1000000)+timo->tv_usec)/rtems_bsdnet_microseconds_per_tick; + if ( ticks > 0 ) { + rtems_event_receive(RTEMS_EVENT_31, (RTEMS_EVENT_ANY|RTEMS_WAIT), ticks, &events); + } +} + +/* + * 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; + /*fatal("read: %m"); */ + } + 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) + fatal("eof on loopback"); + if (errno != EWOULDBLOCK) + fatal("read from loopback: %m"); + + 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; + + strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + ifr.ifr_mtu = mtu; + if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) + fatal("ioctl(SIOCSIFMTU): %m"); + + if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) + fatal("ioctl(PPPIOCSASYNCMAP): %m"); + + if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) + fatal("ioctl (PPPIOCGFLAGS): %m"); + x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT; + x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC; +/* x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC; */ + if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) + fatal("ioctl(PPPIOCSFLAGS): %m"); +} + + +/* + * 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) + warn("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) + fatal("ioctl(PPPIOCSMRU): %m"); + if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) + fatal("ioctl(PPPIOCSRASYNCMAP): %m"); + if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) + fatal("ioctl (PPPIOCGFLAGS): %m"); + x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC; + if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) + fatal("ioctl(PPPIOCSFLAGS): %m"); +} + +/* + * 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) { + error("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) + error("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) { + error("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; +} + +/* + * get_ppp_stats - return statistics for the link. + */ +int +get_ppp_stats(u, stats) + int u; + struct pppd_stats *stats; +{ + struct ifpppstatsreq req; + + memset (&req, 0, sizeof (req)); + strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)); + if (ioctl(sockfd, SIOCGPPPSTATS, &req) < 0) { + error("Couldn't get PPP statistics: %m"); + return 0; + } + stats->bytes_in = req.stats.p.ppp_ibytes; + stats->bytes_out = req.stats.p.ppp_obytes; + return 1; +} + + +#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) { + error("Couldn't set pass-filter in kernel: %m"); + ret = 0; + } + } + if (active->bf_len > 0) { + if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) { + error("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) { + error("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) { + error("ioctl(PPPIOCSFLAGS): %m"); + return 0; + } + if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { + error("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; + + strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { + error("ioctl (SIOCGIFFLAGS): %m"); + return 0; + } + ifr.ifr_flags |= IFF_UP; + if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + error("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) { + error("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. */ + + strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { + error("ioctl (SIOCGIFFLAGS): %m"); + rv = 0; + } else { + ifr.ifr_flags &= ~IFF_UP; + if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + error("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; + + strlcpy(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)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { + if (errno != EADDRNOTAVAIL) + warn("Couldn't remove interface address: %m"); + } + if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { + if (errno != EEXIST) { + error("Couldn't set interface address: %m"); + return 0; + } + warn("Couldn't set interface address: Address %I already exists", 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; + strlcpy(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) + warn("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 status; + struct sockaddr_in address; + struct sockaddr_in netmask; + struct sockaddr_in gateway; + + memset((void *) &address, 0, sizeof(address)); + address.sin_len = sizeof address; + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + + memset((void *) &netmask, 0, sizeof(netmask)); + netmask.sin_len = sizeof netmask; + netmask.sin_addr.s_addr = INADDR_ANY; + netmask.sin_family = AF_INET; + + if (cmd=='s') { + memset((void *) &gateway, 0, sizeof(gateway)); + gateway.sin_len = sizeof gateway; + gateway.sin_family = AF_INET; + gateway.sin_addr.s_addr = g; + + rtems_bsdnet_rtrequest(RTM_ADD, + (struct sockaddr *)&address, + (struct sockaddr *)&gateway, + (struct sockaddr *)&netmask, + (RTF_UP|RTF_GATEWAY|RTF_STATIC), NULL); + } + else { + memset((void *) &gateway, 0, sizeof(gateway)); + gateway.sin_len = sizeof gateway; + gateway.sin_family = AF_INET; + gateway.sin_addr.s_addr = INADDR_ANY; + + rtems_bsdnet_rtrequest(RTM_DELETE, + (struct sockaddr *)&address, + (struct sockaddr *)&gateway, + (struct sockaddr *)&netmask, + (RTF_UP|RTF_STATIC), NULL); + } + + 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)) { + error("Cannot determine ethernet address for proxy ARP"); + return 0; + } + + if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { + error("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) { + error("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) { + error("Couldn't delete proxy arp entry: socket: %m"); + return 0; + } + + if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { + error("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)) { + error("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) { + error("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) { + warn("Couldn't delete proxy arp entry: %m"); + return 0; + } + proxy_arp_addr = 0; + return 1; +} +#endif /* RTM_VERSION */ + + +/* + * get_ether_addr - get the hardware address of an interface on the + * the same subnet as ipaddr. + */ +#define MAX_IFS 32 + +static int +get_ether_addr(ipaddr, hwaddr) + u_int32_t ipaddr; + struct sockaddr_dl *hwaddr; +{ + struct ifreq *ifr, *ifend, *ifp; + u_int32_t ina, mask; + struct sockaddr_dl *dla; + struct ifreq ifreq; + struct ifconf ifc; + struct ifreq ifs[MAX_IFS]; + + ifc.ifc_len = sizeof(ifs); + ifc.ifc_req = ifs; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { + error("ioctl(SIOCGIFCONF): %m"); + return 0; + } + + /* + * Scan through looking for an interface with an Internet + * address on the same subnet as `ipaddr'. + */ + ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); + for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) + ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { + if (ifr->ifr_addr.sa_family == AF_INET) { + ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; + strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); + /* + * Check that the interface is up, and not point-to-point + * or loopback. + */ + if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) + continue; + if ((ifreq.ifr_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. + */ + if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) + continue; + mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; + if ((ipaddr & mask) != (ina & mask)) + continue; + + break; + } + } + + if (ifr >= ifend) + return 0; + info("found interface %s for proxy arp", ifr->ifr_name); + + /* + * Now scan through again looking for a link-level address + * for this interface. + */ + ifp = ifr; + for (ifr = ifc.ifc_req; ifr < ifend; ) { + if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 + && ifr->ifr_addr.sa_family == AF_LINK) { + /* + * Found the link-level address - copy it out + */ + dla = (struct sockaddr_dl *) &ifr->ifr_addr; + BCOPY(dla, hwaddr, dla->sdl_len); + return 1; + } + ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); + } + + 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 ifreq *ifr, *ifend, ifreq; + struct ifconf ifc; + struct ifreq ifs[MAX_IFS]; + + 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. + */ + ifc.ifc_len = sizeof(ifs); + ifc.ifc_req = ifs; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { + warn("ioctl(SIOCGIFCONF): %m"); + return mask; + } + ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); + for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) + ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { + /* + * Check the interface's internet address. + */ + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + ina = ((struct sockaddr_in *) &ifr->ifr_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. + */ + strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) + continue; + if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) + != IFF_UP) + continue; + /* + * Get its netmask and OR it into our mask. + */ + if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) + continue; + mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr; + } + + return mask; +} + +/* + * have_route_to - determine if the system has any route to + * a given IP address. + * For demand mode to work properly, we have to ignore routes + * through our own interface. + */ +int have_route_to(u_int32_t addr) +{ + return -1; +} + +/* + * Use the hostid as part of the random number seed. + */ +int +get_host_seed() +{ + return 17; +} diff --git a/c/src/libnetworking/pppd/upap.c b/c/src/libnetworking/pppd/upap.c index c3c6cf1d6d..b782f26358 100644 --- a/c/src/libnetworking/pppd/upap.c +++ b/c/src/libnetworking/pppd/upap.c @@ -17,9 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -/* static char rcsid[] = "$Id$"; */ -#endif +#define RCSID "$Id$" /* * TODO: @@ -27,13 +25,30 @@ #include #include -#include -#include -#include #include "pppd.h" #include "upap.h" -#define print_string(user, ulen, printer, arg) + +static const char rcsid[] = RCSID; + +static bool hide_password = 1; + +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", 0 }, + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP" }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs" }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication" }, + { NULL } +}; /* * Protocol entry points. @@ -60,6 +75,8 @@ struct protent pap_protent = { 1, "PAP", NULL, + pap_option_list, + NULL, NULL, NULL }; @@ -166,7 +183,7 @@ upap_timeout(arg) if (u->us_transmits >= u->us_maxtransmits) { /* give up in disgust */ - syslog(LOG_ERR, "No response to PAP authenticate-requests"); + error("No response to PAP authenticate-requests"); u->us_clientstate = UPAPCS_BADAUTH; auth_withpeer_fail(u->us_unit, PPP_PAP); return; @@ -253,11 +270,11 @@ upap_protrej(unit) upap_state *u = &upap[unit]; if (u->us_clientstate == UPAPCS_AUTHREQ) { - syslog(LOG_ERR, "PAP authentication failed due to protocol-reject"); + error("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)"); + error("PAP authentication of peer failed (protocol-reject)"); auth_peer_fail(unit, PPP_PAP); } upap_lowerdown(unit); @@ -284,18 +301,18 @@ upap_input(unit, inpacket, l) */ inp = inpacket; if (l < UPAP_HEADERLEN) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.")); + UPAPDEBUG(("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.")); + UPAPDEBUG(("pap_input: rcvd illegal length.")); return; } if (len > l) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.")); + UPAPDEBUG(("pap_input: rcvd short packet.")); return; } len -= UPAP_HEADERLEN; @@ -338,8 +355,6 @@ upap_rauthreq(u, inp, id, len) char *msg; int msglen; - UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.", id)); - if (u->us_serverstate < UPAPSS_LISTEN) return; @@ -359,21 +374,21 @@ upap_rauthreq(u, inp, id, len) /* * Parse user/passwd. */ - if (len < sizeof (u_char)) { - UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.")); + if (len < 1) { + UPAPDEBUG(("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.")); + UPAPDEBUG(("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.")); + UPAPDEBUG(("pap_rauth: rcvd short packet.")); return; } rpasswd = (char *) inp; @@ -382,8 +397,11 @@ upap_rauthreq(u, inp, id, len) * Check the username and password given. */ retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, - rpasswdlen, &msg, &msglen); + rpasswdlen, &msg); BZERO(rpasswd, rpasswdlen); + msglen = strlen(msg); + if (msglen > 255) + msglen = 255; upap_sresp(u, retcode, id, msg, msglen); @@ -413,25 +431,26 @@ upap_rauthack(u, inp, id, 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; + if (len < 1) { + UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthack: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } } - msg = (char *) inp; - PRINTMSG(msg, msglen); u->us_clientstate = UPAPCS_OPEN; @@ -452,29 +471,30 @@ upap_rauthnak(u, inp, id, 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; + if (len < 1) { + UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } } - msg = (char *) inp; - PRINTMSG(msg, msglen); u->us_clientstate = UPAPCS_BADAUTH; - syslog(LOG_ERR, "PAP authentication failed"); + error("PAP authentication failed"); auth_withpeer_fail(u->us_unit, PPP_PAP); } @@ -506,8 +526,6 @@ upap_sauthreq(u) 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; @@ -520,7 +538,7 @@ upap_sauthreq(u) static void upap_sresp(u, code, id, msg, msglen) upap_state *u; - int code, id; + u_char code, id; char *msg; int msglen; { @@ -537,8 +555,6 @@ upap_sresp(u, code, id, msg, msglen) 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)); } /* @@ -592,7 +608,10 @@ upap_printpkt(p, plen, printer, arg) printer(arg, " user="); print_string(user, ulen, printer, arg); printer(arg, " password="); - print_string(pwd, wlen, printer, arg); + if (!hide_password) + print_string(pwd, wlen, printer, arg); + else + printer(arg, ""); break; case UPAP_AUTHACK: case UPAP_AUTHNAK: diff --git a/c/src/libnetworking/pppd/upap.h b/c/src/libnetworking/pppd/upap.h index 510efa3151..42d6f4f0f6 100644 --- a/c/src/libnetworking/pppd/upap.h +++ b/c/src/libnetworking/pppd/upap.h @@ -22,7 +22,7 @@ /* * Packet header = Code, id, length. */ -#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) +#define UPAP_HEADERLEN 4 /* diff --git a/c/src/libnetworking/pppd/utils.c b/c/src/libnetworking/pppd/utils.c new file mode 100644 index 0000000000..b1bdb5d754 --- /dev/null +++ b/c/src/libnetworking/pppd/utils.c @@ -0,0 +1,872 @@ +/* + * utils.c - various utility functions used in pppd. + * + * Copyright (c) 1999 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. + */ + +#define RCSID "$Id$" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SVR4 +#include +#endif + +#include "pppd.h" + +static const char rcsid[] = RCSID; + +#if defined(SUNOS4) +extern char *strerror(); +#endif + +static void pr_log __P((void *, char *, ...)); +static void logit __P((int, char *, va_list)); +static void vslp_printer __P((void *, char *, ...)); +static void format_packet __P((u_char *, int, void (*) (void *, char *, ...), + void *)); + +struct buffer_info { + char *ptr; + int len; +}; + +/* + * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t +strlcpy(dest, src, len) + char *dest; + const char *src; + size_t len; +{ + size_t ret = strlen(src); + + if (len != 0) { + if (ret < len) + strcpy(dest, src); + else { + strncpy(dest, src, len - 1); + dest[len-1] = 0; + } + } + return ret; +} + +/* + * strlcat - like strcat/strncat, doesn't overflow destination buffer, + * always leaves destination null-terminated (for len > 0). + */ +size_t +strlcat(dest, src, len) + char *dest; + const char *src; + size_t len; +{ + size_t dlen = strlen(dest); + + return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); +} + + +/* + * slprintf - 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), %v (visible string), + * %q (quoted string), %t (current time) and %I (IP address) formats. + * Doesn't do floating-point formats. + * Returns the number of chars put into buf. + */ +int +slprintf __V((char *buf, int buflen, char *fmt, ...)) +{ + va_list args; + int n; + +#if defined(__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 = vslprintf(buf, buflen, fmt, args); + va_end(args); + return n; +} + +/* + * vslprintf - like slprintf, takes a va_list instead of a list of args. + */ +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) + +int +vslprintf(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; + u_int32_t ip; + static char hexchars[] = "0123456789abcdef"; + struct buffer_info bufinfo; + + 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 = 0; + prec = -1; + 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 { + prec = 0; + 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': + 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': + ip = va_arg(args, u_int32_t); + ip = ntohl(ip); + slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, + (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); + str = num; + break; + case 'r': + f = va_arg(args, char *); +#ifndef __powerpc__ + n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list)); +#else + /* On the powerpc, a va_list is an array of 1 structure */ + n = vslprintf(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 && n > prec) + 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; + case 'P': /* print PPP packet */ + bufinfo.ptr = buf; + bufinfo.len = buflen + 1; + p = va_arg(args, unsigned char *); + n = va_arg(args, int); + format_packet(p, n, vslp_printer, &bufinfo); + buf = bufinfo.ptr; + buflen = bufinfo.len - 1; + continue; + case 'B': + p = va_arg(args, unsigned char *); + for (n = prec; n > 0; --n) { + c = *p++; + if (fillch == ' ') + OUTCHAR(' '); + OUTCHAR(hexchars[(c >> 4) & 0xf]); + OUTCHAR(hexchars[c & 0xf]); + } + 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; +} + +/* + * vslp_printer - used in processing a %P format + */ +static void +vslp_printer __V((void *arg, char *fmt, ...)) +{ + int n; + va_list pvar; + struct buffer_info *bi; + +#if defined(__STDC__) + va_start(pvar, fmt); +#else + void *arg; + char *fmt; + va_start(pvar); + arg = va_arg(pvar, void *); + fmt = va_arg(pvar, char *); +#endif + + bi = (struct buffer_info *) arg; + n = vslprintf(bi->ptr, bi->len, fmt, pvar); + va_end(pvar); + + bi->ptr += n; + bi->len -= n; +} + +/* + * 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; +{ + strlcpy(line, prefix, sizeof(line)); + linep = line + strlen(line); + format_packet(p, len, pr_log, NULL); +} + +/* + * format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. + */ +static void +format_packet(p, len, printer, arg) + u_char *p; + int len; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + int i, n; + u_short proto; + 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 { + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (proto == (protp->protocol & ~0x8000)) + break; + if (protp != 0 && protp->data_name != 0) { + printer(arg, "[%s data]", protp->data_name); + if (len > 8) + printer(arg, "%.8B ...", p); + else + printer(arg, "%.*B", len, p); + len = 0; + } else + printer(arg, "[proto=0x%x]", proto); + } + } + + if (len > 32) + printer(arg, "%.32B ...", p); + else + printer(arg, "%.*B", len, p); +} + +static void +pr_log __V((void *arg, char *fmt, ...)) +{ + int n; + va_list pvar; + char buf[256]; + +#if defined(__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 = vslprintf(buf, sizeof(buf), fmt, pvar); + va_end(pvar); + + if (linep + n + 1 > line + sizeof(line)) { + linep = line; + } + strlcpy(linep, buf, line + sizeof(line) - linep); + 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) __P((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, "\""); +} + +/* + * logit - does the hard work for fatal et al. + */ +static void +logit(level, fmt, args) + int level; + char *fmt; + va_list args; +{ + int n; + char buf[256]; + + n = vslprintf(buf, sizeof(buf), fmt, args); +/* if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { */ + if (log_to_fd >= 0 && (debug)) { + if (buf[n-1] != '\n') + buf[n++] = '\n'; + if (write(log_to_fd, buf, n) != n) + log_to_fd = -1; + } +} + +/* + * fatal - log an error message and die horribly. + */ +void +pppd_fatal __V((char *fmt, ...)) +{ + va_list pvar; + +#if defined(__STDC__) + va_start(pvar, fmt); +#else + char *fmt; + va_start(pvar); + fmt = va_arg(pvar, char *); +#endif + + logit(LOG_ERR, fmt, pvar); + va_end(pvar); + + die(1); /* as promised */ +} + +/* + * error - log an error message. + */ +void +pppd_error __V((char *fmt, ...)) +{ + va_list pvar; + +#if defined(__STDC__) + va_start(pvar, fmt); +#else + char *fmt; + va_start(pvar); + fmt = va_arg(pvar, char *); +#endif + + logit(LOG_ERR, fmt, pvar); + va_end(pvar); +} + +/* + * warn - log a warning message. + */ +void +pppd_warn __V((char *fmt, ...)) +{ + va_list pvar; + +#if defined(__STDC__) + va_start(pvar, fmt); +#else + char *fmt; + va_start(pvar); + fmt = va_arg(pvar, char *); +#endif + + logit(LOG_WARNING, fmt, pvar); + va_end(pvar); +} + +/* + * notice - log a notice-level message. + */ +void +pppd_notice __V((char *fmt, ...)) +{ + va_list pvar; + +#if defined(__STDC__) + va_start(pvar, fmt); +#else + char *fmt; + va_start(pvar); + fmt = va_arg(pvar, char *); +#endif + + logit(LOG_NOTICE, fmt, pvar); + va_end(pvar); +} + +/* + * info - log an informational message. + */ +void +pppd_info __V((char *fmt, ...)) +{ + va_list pvar; + +#if defined(__STDC__) + va_start(pvar, fmt); +#else + char *fmt; + va_start(pvar); + fmt = va_arg(pvar, char *); +#endif + + logit(LOG_INFO, fmt, pvar); + va_end(pvar); +} + +/* + * dbglog - log a debug message. + */ +void +pppd_dbglog __V((char *fmt, ...)) +{ + va_list pvar; + +#if defined(__STDC__) + va_start(pvar, fmt); +#else + char *fmt; + va_start(pvar); + fmt = va_arg(pvar, char *); +#endif + + logit(LOG_DEBUG, fmt, pvar); + va_end(pvar); +} + +/* Procedures for locking the serial device using a lock file. */ +#ifndef LOCK_DIR +#ifdef _linux_ +#define LOCK_DIR "/var/lock" +#else +#ifdef SVR4 +#define LOCK_DIR "/var/spool/locks" +#else +#define LOCK_DIR "/var/spool/lock" +#endif +#endif +#endif /* LOCK_DIR */ + +static char lock_file[MAXPATHLEN]; + +/* + * lock - create a lock file for the named device + */ +int +lock(dev) + char *dev; +{ +#ifdef LOCKLIB + int result; + + result = mklock (dev, (void *) 0); + if (result == 0) { + strlcpy(lock_file, sizeof(lock_file), dev); + return 0; + } + + if (result > 0) + notice("Device %s is locked by pid %d", dev, result); + else + error("Can't create lock file %s", lock_file); + return -1; + +#else /* LOCKLIB */ + + char lock_buffer[12]; + int fd, pid, n; + +#ifdef SVR4 + struct stat sbuf; + + if (stat(dev, &sbuf) < 0) { + error("Can't get device number for %s: %m", dev); + return -1; + } + if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { + error("Can't lock %s: not a character device", dev); + return -1; + } + slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", + LOCK_DIR, major(sbuf.st_dev), + major(sbuf.st_rdev), minor(sbuf.st_rdev)); +#else + char *p; + + if ((p = strrchr(dev, '/')) != NULL) + dev = p + 1; + slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); +#endif + + while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { + if (errno != EEXIST) { + error("Can't create lock file %s: %m", lock_file); + break; + } + + /* Read the lock file to find out who has the device locked. */ + fd = open(lock_file, O_RDONLY, 0); + if (fd < 0) { + if (errno == ENOENT) /* This is just a timing problem. */ + continue; + error("Can't open existing lock file %s: %m", lock_file); + break; + } +#ifndef LOCK_BINARY + n = read(fd, lock_buffer, 11); +#else + n = read(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + fd = -1; + if (n <= 0) { + error("Can't read pid from lock file %s", lock_file); + break; + } + + /* See if the process still exists. */ +#ifndef LOCK_BINARY + lock_buffer[n] = 0; + pid = atoi(lock_buffer); +#endif /* LOCK_BINARY */ + if (pid == getpid()) + return 1; /* somebody else locked it for us */ + if (pid == 0 + || (kill(pid, 0) == -1 && errno == ESRCH)) { + if (unlink (lock_file) == 0) { + notice("Removed stale lock on %s (pid %d)", dev, pid); + continue; + } + warn("Couldn't remove stale lock on %s", dev); + } else + notice("Device %s is locked by pid %d", dev, pid); + break; + } + + if (fd < 0) { + lock_file[0] = 0; + return -1; + } + + pid = getpid(); +#ifndef LOCK_BINARY + slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof (pid)); +#endif + close(fd); + return 0; + +#endif +} + +/* + * relock - called to update our lockfile when we are about to detach, + * thus changing our pid (we fork, the child carries on, and the parent dies). + * Note that this is called by the parent, with pid equal to the pid + * of the child. This avoids a potential race which would exist if + * we had the child rewrite the lockfile (the parent might die first, + * and another process could think the lock was stale if it checked + * between when the parent died and the child rewrote the lockfile). + */ +int +relock(pid) + int pid; +{ +#ifdef LOCKLIB + /* XXX is there a way to do this? */ + return -1; +#else /* LOCKLIB */ + + int fd; + char lock_buffer[12]; + + if (lock_file[0] == 0) + return -1; + fd = open(lock_file, O_WRONLY, 0); + if (fd < 0) { + error("Couldn't reopen lock file %s: %m", lock_file); + lock_file[0] = 0; + return -1; + } + +#ifndef LOCK_BINARY + slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); + write (fd, lock_buffer, 11); +#else + write(fd, &pid, sizeof(pid)); +#endif /* LOCK_BINARY */ + close(fd); + return 0; + +#endif /* LOCKLIB */ +} + +/* + * unlock - remove our lockfile + */ +void +unlock() +{ + if (lock_file[0]) { +#ifdef LOCKLIB + (void) rmlock(lock_file, (void *) 0); +#else + unlink(lock_file); +#endif + lock_file[0] = 0; + } +} + -- cgit v1.2.3