summaryrefslogtreecommitdiffstats
path: root/cpukit/pppd
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2001-08-16 20:42:09 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2001-08-16 20:42:09 +0000
commit2f1b9304ac4ba89a2dcb6047cb584a5603a33987 (patch)
treef2339e3f2230b73ee4818d55d4154795e712d803 /cpukit/pppd
parent4b3c197fc0912a22b07affd7caef344ce301840a (diff)
downloadrtems-2f1b9304ac4ba89a2dcb6047cb584a5603a33987.tar.bz2
2001-08-16 Mike Siers <mikes@poliac.com>
* 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.
Diffstat (limited to '')
-rw-r--r--cpukit/pppd/Makefile.am35
-rw-r--r--cpukit/pppd/README56
-rw-r--r--cpukit/pppd/STATUS27
-rw-r--r--cpukit/pppd/auth.c733
-rw-r--r--cpukit/pppd/cbcp.c431
-rw-r--r--cpukit/pppd/cbcp.h26
-rw-r--r--cpukit/pppd/ccp.c194
-rw-r--r--cpukit/pppd/ccp.h12
-rw-r--r--cpukit/pppd/chap.c122
-rw-r--r--cpukit/pppd/chap.h4
-rw-r--r--cpukit/pppd/chap_ms.c47
-rw-r--r--cpukit/pppd/chat.c146
-rw-r--r--cpukit/pppd/demand.c9
-rw-r--r--cpukit/pppd/example/README6
-rw-r--r--cpukit/pppd/example/init.c24
-rw-r--r--cpukit/pppd/example/netconfig.h37
-rw-r--r--cpukit/pppd/example/ppp.conf27
-rw-r--r--cpukit/pppd/example/pppdapp.c146
-rw-r--r--cpukit/pppd/example/system.h42
-rw-r--r--cpukit/pppd/fsm.c78
-rw-r--r--cpukit/pppd/fsm.h2
-rw-r--r--cpukit/pppd/ipcp.c546
-rw-r--r--cpukit/pppd/ipcp.h25
-rw-r--r--cpukit/pppd/ipxcp.c298
-rw-r--r--cpukit/pppd/ipxcp.h24
-rw-r--r--cpukit/pppd/lcp.c269
-rw-r--r--cpukit/pppd/lcp.h26
-rw-r--r--cpukit/pppd/magic.c11
-rw-r--r--cpukit/pppd/options.c1570
-rw-r--r--cpukit/pppd/patchlevel.h4
-rw-r--r--cpukit/pppd/pathnames.h39
-rw-r--r--cpukit/pppd/pppd.81480
-rw-r--r--cpukit/pppd/pppd.h377
-rw-r--r--cpukit/pppd/rtemsmain.c903
-rw-r--r--cpukit/pppd/rtemspppd.c173
-rw-r--r--cpukit/pppd/rtemspppd.h38
-rw-r--r--cpukit/pppd/sys-rtems.c1322
-rw-r--r--cpukit/pppd/upap.c121
-rw-r--r--cpukit/pppd/upap.h2
-rw-r--r--cpukit/pppd/utils.c872
40 files changed, 8412 insertions, 1892 deletions
diff --git a/cpukit/pppd/Makefile.am b/cpukit/pppd/Makefile.am
index 836d2ab110..9aab295eb3 100644
--- a/cpukit/pppd/Makefile.am
+++ b/cpukit/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/cpukit/pppd/README b/cpukit/pppd/README
index 8002d3e280..0615100344 100644
--- a/cpukit/pppd/README
+++ b/cpukit/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 <dot@comarch.pl> 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 <dot@comarch.pl> 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 <mikes@poliac.com>
+who added an example test.
+=================================================================
diff --git a/cpukit/pppd/STATUS b/cpukit/pppd/STATUS
index 0e4980cbbc..3bcf2e205b 100644
--- a/cpukit/pppd/STATUS
+++ b/cpukit/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 <rgaller@et.put.poznan.pl>)
-
-+ 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/cpukit/pppd/auth.c b/cpukit/pppd/auth.c
index f5cff9ac3d..f08a89a0c1 100644
--- a/cpukit/pppd/auth.c
+++ b/cpukit/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 <stdio.h>
#include <stddef.h>
-#include <stdlib.h>
+#include <stdlib.h>
#include <unistd.h>
-#include <syslog.h>
#include <pwd.h>
+#include <grp.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
-
#include <fcntl.h>
#if defined(_PATH_LASTLOG) && defined(_linux_)
#include <lastlog.h>
@@ -55,7 +52,17 @@
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-/* #include <stbconfig.h> */
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#endif
+
+#ifdef HAS_SHADOW
+#include <shadow.h>
+#ifndef PW_PPP
+#define PW_PPP PW_LOGIN
+#endif
+#endif
#include "pppd.h"
#include "fsm.h"
@@ -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;
}
/*
@@ -782,41 +1052,6 @@ bad_ip_adrs(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.
*/
static void
@@ -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/cpukit/pppd/cbcp.c b/cpukit/pppd/cbcp.c
deleted file mode 100644
index 147e56a07b..0000000000
--- a/cpukit/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 <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
-
-#include "pppd.h"
-#include "cbcp.h"
-#include "fsm.h"
-#include "lcp.h"
-#include "ipcp.h"
-
-/*
- * Protocol entry points.
- */
-static void cbcp_init __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/cpukit/pppd/cbcp.h b/cpukit/pppd/cbcp.h
deleted file mode 100644
index c2ab3f6899..0000000000
--- a/cpukit/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/cpukit/pppd/ccp.c b/cpukit/pppd/ccp.c
index 1467c6e411..094a96d8f5 100644
--- a/cpukit/pppd/ccp.c
+++ b/cpukit/pppd/ccp.c
@@ -25,20 +25,60 @@
* OR MODIFICATIONS.
*/
-#ifndef lint
-/* static char rcsid[] = "$Id$"; */
-#endif
+#define RCSID "$Id$"
+#include <stdlib.h>
#include <string.h>
-#include <syslog.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
#include "pppd.h"
#include "fsm.h"
#include "ccp.h"
#include <net/ppp-comp.h>
+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
@@ -130,6 +172,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.
*/
static void
@@ -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/cpukit/pppd/ccp.h b/cpukit/pppd/ccp.h
index af421d48c3..609d858c5e 100644
--- a/cpukit/pppd/ccp.h
+++ b/cpukit/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/cpukit/pppd/chap.c b/cpukit/pppd/chap.c
index de80fdf666..15d0210369 100644
--- a/cpukit/pppd/chap.c
+++ b/cpukit/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 <string.h>
#include <sys/types.h>
#include <sys/time.h>
-#include <syslog.h>
#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 <stdlib.h> */
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/cpukit/pppd/chap.h b/cpukit/pppd/chap.h
index 6e2cc45e89..945d051d06 100644
--- a/cpukit/pppd/chap.h
+++ b/cpukit/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/cpukit/pppd/chap_ms.c b/cpukit/pppd/chap_ms.c
index 2de98dbb66..81a57bb5aa 100644
--- a/cpukit/pppd/chap_ms.c
+++ b/cpukit/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 <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
-#include <syslog.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
@@ -57,6 +55,8 @@
#include <des.h>
#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/cpukit/pppd/chat.c b/cpukit/pppd/chat.c
index eca2066e93..31273714b4 100644
--- a/cpukit/pppd/chat.c
+++ b/cpukit/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/cpukit/pppd/demand.c b/cpukit/pppd/demand.c
index a1910f258f..1f2e9932d4 100644
--- a/cpukit/pppd/demand.c
+++ b/cpukit/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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
-#include <syslog.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/types.h>
@@ -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/cpukit/pppd/example/README b/cpukit/pppd/example/README
new file mode 100644
index 0000000000..786d03844b
--- /dev/null
+++ b/cpukit/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/cpukit/pppd/example/init.c b/cpukit/pppd/example/init.c
new file mode 100644
index 0000000000..f35d195bf2
--- /dev/null
+++ b/cpukit/pppd/example/init.c
@@ -0,0 +1,24 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtemspppd.h>
+
+#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/cpukit/pppd/example/netconfig.h b/cpukit/pppd/example/netconfig.h
new file mode 100644
index 0000000000..6a95cce189
--- /dev/null
+++ b/cpukit/pppd/example/netconfig.h
@@ -0,0 +1,37 @@
+
+#ifndef NETCONFIG_H_
+#define NETCONFIG_H_
+
+#include <bsp.h>
+
+/* 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/cpukit/pppd/example/ppp.conf b/cpukit/pppd/example/ppp.conf
new file mode 100644
index 0000000000..094b1946a8
--- /dev/null
+++ b/cpukit/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/cpukit/pppd/example/pppdapp.c b/cpukit/pppd/example/pppdapp.c
new file mode 100644
index 0000000000..59e5029088
--- /dev/null
+++ b/cpukit/pppd/example/pppdapp.c
@@ -0,0 +1,146 @@
+
+#include <stdio.h>
+#include <rtemspppd.h>
+#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/cpukit/pppd/example/system.h b/cpukit/pppd/example/system.h
new file mode 100644
index 0000000000..87678da1b6
--- /dev/null
+++ b/cpukit/pppd/example/system.h
@@ -0,0 +1,42 @@
+
+#ifndef SYSTEM_H
+#define SYSTEM_H
+
+#include <rtems.h>
+#include <tty_drv.h>
+
+/* functions */
+extern rtems_task Init(rtems_task_argument argument);
+
+#include <bsp.h>
+
+#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 <confdefs.h>
+
+#endif
diff --git a/cpukit/pppd/fsm.c b/cpukit/pppd/fsm.c
index 0d50b35c6c..07a8c11f1d 100644
--- a/cpukit/pppd/fsm.c
+++ b/cpukit/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 <stdio.h>
#include <string.h>
#include <sys/types.h>
-#include <syslog.h>
#include "pppd.h"
#include "fsm.h"
+static const char rcsid[] = RCSID;
+
static void fsm_timeout __P((void *));
static void fsm_rconfreq __P((fsm *, int, u_char *, int));
static void fsm_rconfack __P((fsm *, int, u_char *, int));
@@ -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/cpukit/pppd/fsm.h b/cpukit/pppd/fsm.h
index f289429fdc..c94a68e6ce 100644
--- a/cpukit/pppd/fsm.h
+++ b/cpukit/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/cpukit/pppd/ipcp.c b/cpukit/pppd/ipcp.c
index 5553d3194d..57245721fa 100644
--- a/cpukit/pppd/ipcp.c
+++ b/cpukit/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 <stdio.h>
#include <string.h>
-#include <syslog.h>
#include <netdb.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-/* #include <stbconfig.h> */
+#include <arpa/inet.h>
#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 */
@@ -89,6 +94,71 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
};
/*
+ * 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.
*/
static void ipcp_init __P((int));
@@ -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/cpukit/pppd/ipcp.h b/cpukit/pppd/ipcp.h
index e2c7eb44db..8c5aca861d 100644
--- a/cpukit/pppd/ipcp.h
+++ b/cpukit/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/cpukit/pppd/ipxcp.c b/cpukit/pppd/ipxcp.c
index d55ace569e..4e408a00f9 100644
--- a/cpukit/pppd/ipxcp.c
+++ b/cpukit/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 <stdio.h>
#include <string.h>
-#include <syslog.h>
+#include <unistd.h>
+#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -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,7 +79,7 @@ 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 */
@@ -84,6 +87,50 @@ static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
};
/*
+ * 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/cpukit/pppd/ipxcp.h b/cpukit/pppd/ipxcp.h
index 139a7260b3..47f680d70c 100644
--- a/cpukit/pppd/ipxcp.h
+++ b/cpukit/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/cpukit/pppd/lcp.c b/cpukit/pppd/lcp.c
index e58b3dcba2..781f5569ad 100644
--- a/cpukit/pppd/lcp.c
+++ b/cpukit/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 <stdio.h>
#include <string.h>
-#include <syslog.h>
-#include <assert.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
+#include <stdlib.h>
#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,10 +209,10 @@ 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" : \
@@ -149,6 +220,37 @@ int lcp_loopbackfail = DEFLOOPBACKFAIL;
/*
+ * 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.
*/
static void
@@ -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/cpukit/pppd/lcp.h b/cpukit/pppd/lcp.h
index 42260f3a63..16ba4cc44b 100644
--- a/cpukit/pppd/lcp.h
+++ b/cpukit/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/cpukit/pppd/magic.c b/cpukit/pppd/magic.c
index 67d6b6ca90..c571ef792e 100644
--- a/cpukit/pppd/magic.c
+++ b/cpukit/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 <stdio.h>
-#include <unistd.h>
#include <stdlib.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include "pppd.h"
#include "magic.h"
+static const char rcsid[] = RCSID;
+
extern long mrand48 __P((void));
extern void srand48 __P((long));
@@ -64,7 +64,7 @@ magic()
* Substitute procedures for those systems which don't have
* drand48 et al.
*/
-/* #include <stdlib.h> */
+
double
drand48()
{
@@ -83,4 +83,3 @@ long seedval;
{
srand((int)seedval);
}
-
diff --git a/cpukit/pppd/options.c b/cpukit/pppd/options.c
index 759ed988f8..3f56dbf892 100644
--- a/cpukit/pppd/options.c
+++ b/cpukit/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 <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
-#include <limits.h>
-/* #include <stdlib.h> */
+#include <fcntl.h>
+#include <stdlib.h>
#include <termios.h>
-#include <syslog.h>
#include <string.h>
#include <netdb.h>
#include <pwd.h>
@@ -36,6 +33,9 @@
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#ifdef PLUGIN
+#include <dlfcn.h>
+#endif
#ifdef PPP_FILTER
#include <pcap.h>
#include <pcap-int.h> /* 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 <net/ppp-comp.h>
-#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, &notty,
+ "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\
+ <device> Communicate over the named device\n\
+ <speed> Set the baud rate to <speed>\n\
+ <loc>:<rem> Set the local and/or remote interface IP\n\
+ addresses. Either one may be omitted.\n\
+ asyncmap <n> Set the desired async map to hex <n>\n\
+ auth Require authentication from peer\n\
+ connect <p> Invoke shell command <p> to set up the serial line\n\
+ crtscts Use hardware RTS/CTS flow control\n\
+ defaultroute Add default route through interface\n\
+ file <f> Take options from file <f>\n\
+ modem Use modem control lines\n\
+ mru <n> Set MRU value to <n> for negotiation\n\
+See pppd(8) for more options.\n\
+";
+
/*
* 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 \.
* \<newline> is ignored.
*/
+int
+getword(f, word, newlinep, filename)
+ FILE *f;
+ char *word;
+ int *newlinep;
+ char *filename;
+{
+ int c, len, escape;
+ int quoted, comment;
+ int value, digit, got, n;
+
+#define isoctal(c) ((c) >= '0' && (c) < '8')
+
+ *newlinep = 0;
+ len = 0;
+ escape = 0;
+ comment = 0;
+
+ /*
+ * First skip white-space and comments.
+ */
+ for (;;) {
+ c = getc(f);
+ if (c == EOF)
+ break;
+
+ /*
+ * A newline means the end of a comment; backslash-newline
+ * is ignored. Note that we cannot have escape && comment.
+ */
+ if (c == '\n') {
+ if (!escape) {
+ *newlinep = 1;
+ comment = 0;
+ } else
+ escape = 0;
+ continue;
+ }
+
+ /*
+ * Ignore characters other than newline in a comment.
+ */
+ if (comment)
+ continue;
+
+ /*
+ * If this character is escaped, we have a word start.
+ */
+ if (escape)
+ break;
+
+ /*
+ * If this is the escape character, look at the next character.
+ */
+ if (c == '\\') {
+ escape = 1;
+ continue;
+ }
+
+ /*
+ * If this is the start of a comment, ignore the rest of the line.
+ */
+ if (c == '#') {
+ comment = 1;
+ continue;
+ }
+
+ /*
+ * A non-whitespace character is the start of a word.
+ */
+ if (!isspace(c))
+ break;
+ }
+
+ /*
+ * Save the delimiter for quoted strings.
+ */
+ if (!escape && (c == '"' || c == '\'')) {
+ quoted = c;
+ c = getc(f);
+ } else
+ quoted = 0;
+
+ /*
+ * Process characters until the end of the word.
+ */
+ while (c != EOF) {
+ if (escape) {
+ /*
+ * This character is escaped: backslash-newline is ignored,
+ * various other characters indicate particular values
+ * as for C backslash-escapes.
+ */
+ escape = 0;
+ if (c == '\n') {
+ c = getc(f);
+ continue;
+ }
+
+ got = 0;
+ switch (c) {
+ case 'a':
+ value = '\a';
+ break;
+ case 'b':
+ value = '\b';
+ break;
+ case 'f':
+ value = '\f';
+ break;
+ case 'n':
+ value = '\n';
+ break;
+ case 'r':
+ value = '\r';
+ break;
+ case 's':
+ value = ' ';
+ break;
+ case 't':
+ value = '\t';
+ break;
+
+ default:
+ if (isoctal(c)) {
+ /*
+ * \ddd octal sequence
+ */
+ value = 0;
+ for (n = 0; n < 3 && isoctal(c); ++n) {
+ value = (value << 3) + (c & 07);
+ c = getc(f);
+ }
+ got = 1;
+ break;
+ }
+
+ if (c == 'x') {
+ /*
+ * \x<hex_string> sequence
+ */
+ value = 0;
+ c = getc(f);
+ for (n = 0; n < 2 && isxdigit(c); ++n) {
+ digit = toupper(c) - '0';
+ if (digit > 10)
+ digit += '0' + 10 - 'A';
+ value = (value << 4) + digit;
+ c = getc (f);
+ }
+ got = 1;
+ break;
+ }
+
+ /*
+ * Otherwise the character stands for itself.
+ */
+ value = c;
+ break;
+ }
+
+ /*
+ * Store the resulting character for the escape sequence.
+ */
+ if (len < MAXWORDLEN-1)
+ word[len] = value;
+ ++len;
+
+ if (!got)
+ c = getc(f);
+ continue;
+
+ }
+
+ /*
+ * Not escaped: see if we've reached the end of the word.
+ */
+ if (quoted) {
+ if (c == quoted)
+ break;
+ } else {
+ if (isspace(c) || c == '#') {
+ ungetc (c, f);
+ break;
+ }
+ }
+
+ /*
+ * Backslash starts an escape sequence.
+ */
+ if (c == '\\') {
+ escape = 1;
+ c = getc(f);
+ continue;
+ }
+
+ /*
+ * An ordinary character: store it in the word and get another.
+ */
+ if (len < MAXWORDLEN-1)
+ word[len] = c;
+ ++len;
+
+ c = getc(f);
+ }
+
+ /*
+ * End of the word: check for errors.
+ */
+ if (c == EOF) {
+ if (ferror(f)) {
+ if (errno == 0)
+ errno = EIO;
+ option_error("Error reading %s: %m", filename);
+ die(1);
+ }
+ /*
+ * If len is zero, then we didn't find a word before the
+ * end of the file.
+ */
+ if (len == 0)
+ return 0;
+ }
+
+ /*
+ * Warn if the word was too long, and append a terminating null.
+ */
+ if (len >= MAXWORDLEN) {
+ option_error("warning: word in file %s too long (%.20s...)",
+ filename, word);
+ len = MAXWORDLEN - 1;
+ }
+ word[len] = 0;
+
+ return 1;
+
+#undef isoctal
+
+}
+
+/*
+ * number_option - parse an unsigned numeric parameter for an option.
+ */
+static int
+number_option(str, valp, base)
+ char *str;
+ u_int32_t *valp;
+ int base;
+{
+ char *ptr;
+
+ *valp = strtoul(str, &ptr, base);
+ if (ptr == str) {
+ option_error("invalid numeric parameter '%s' for %s option",
+ str, current_option);
+ return 0;
+ }
+ return 1;
+}
+
+
+/*
+ * int_option - like number_option, but valp is int *,
+ * the base is assumed to be 0, and *valp is not changed
+ * if there is an error.
+ */
+int
+int_option(str, valp)
+ char *str;
+ int *valp;
+{
+ u_int32_t v;
+
+ if (!number_option(str, &v, 0))
+ return 0;
+ *valp = (int) v;
+ return 1;
+}
+
- /*
+/*
* The following procedures parse options.
*/
/*
* readfile - take commands from a file.
*/
-
+static int
+readfile(argv)
+ char **argv;
+{
+ return options_from_file(*argv, 1, 1, privileged_option);
+}
+
/*
* callfile - take commands from /etc/ppp/peers/<name>.
* Name may not contain /../, start with / or ../, or end in /..
*/
- /*
- * 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/cpukit/pppd/patchlevel.h b/cpukit/pppd/patchlevel.h
index 02bf115c52..54d88b8a66 100644
--- a/cpukit/pppd/patchlevel.h
+++ b/cpukit/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/cpukit/pppd/pathnames.h b/cpukit/pppd/pathnames.h
index b954204f5c..0a4f6e69f2 100644
--- a/cpukit/pppd/pathnames.h
+++ b/cpukit/pppd/pathnames.h
@@ -8,23 +8,36 @@
#include <paths.h>
#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/cpukit/pppd/pppd.8 b/cpukit/pppd/pppd.8
new file mode 100644
index 0000000000..227345ff5f
--- /dev/null
+++ b/cpukit/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 <tty_name>
+Communicate over the named device. The string "/dev/" is prepended if
+necessary. If no device name is given, or if the name of the terminal
+connected to the standard input is given, pppd will use that terminal,
+and will not fork to put itself in the background. A value for this
+option from a privileged source cannot be overridden by a
+non-privileged user.
+.TP
+.I <speed>
+Set the baud rate to <speed> (a decimal number). On systems such as
+4.4BSD and NetBSD, any speed can be specified. Other systems
+(e.g. SunOS) allow only a limited set of speeds.
+.TP
+.B asyncmap \fI<map>
+Set the async character map to <map>. This map describes which
+control characters cannot be successfully received over the serial
+line. Pppd will ask the peer to send these characters as a 2-byte
+escape sequence. The argument is a 32 bit hex number with each bit
+representing a character to escape. Bit 0 (00000001) represents the
+character 0x00; bit 31 (80000000) represents the character 0x1f or ^_.
+If multiple \fIasyncmap\fR options are given, the values are ORed
+together. If no \fIasyncmap\fR option is given, no async character
+map will be negotiated for the receive direction; the peer should then
+escape \fIall\fR control characters. To escape transmitted
+characters, use the \fIescape\fR option.
+.TP
+.B auth
+Require the peer to authenticate itself before allowing network
+packets to be sent or received. 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 <local_IP_address>\fB:\fI<remote_IP_address>
+Set the local and/or remote interface IP addresses. Either one may be
+omitted. The IP addresses can be specified with a host name or in
+decimal dot notation (e.g. 150.234.56.78). The default local
+address is the (first) IP address of the system (unless the
+\fInoipdefault\fR
+option is given). The remote address will be obtained from the peer
+if not specified in any option. Thus, in simple cases, this option is
+not required. If a local and/or remote IP address is specified with
+this option, pppd
+will not accept a different value from the peer in the IPCP
+negotiation, unless the \fIipcp-accept-local\fR and/or
+\fIipcp-accept-remote\fR options are given, respectively.
+.TP
+.B ipv6 \fI<local_interface_identifier>\fR,\fI<remote_interface_identifier>
+Set the local and/or remote 64-bit interface identifier. Either one may be
+omitted. The identifier must be specified in standard ascii notation of
+IPv6 addresses (e.g. ::dead:beef). If the
+\fIipv6cp-use-ipaddr\fR
+option is given, the local identifier is the local IPv4 address (see above).
+On systems which supports a unique persistent id, such as EUI-48 derived
+from the Ethernet MAC address, \fIipv6cp-use-persistent\fR option can be
+used to replace the \fIipv6 <local>,<remote>\fR option. Otherwise the
+identifier is randomized.
+.TP
+.B 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<string>
+Set the name of the router. This is a string and is sent to the peer
+as information data.
+.TP
+.B ipx-routing \fIn
+Set the routing protocol to be received by this option. More than one
+instance of \fIipx-routing\fR may be specified. The '\fInone\fR'
+option (0) may be specified as the only instance of ipx-routing. The
+values may be \fI0\fR for \fINONE\fR, \fI2\fR for \fIRIP/SAP\fR, and
+\fI4\fR for \fINLSP\fR.
+.TP
+.B ipxcp-accept-local
+Accept the peer's NAK for the node number specified in the ipx-node
+option. If a node number was specified, and non-zero, the default is
+to insist that the value be used. If you include this option then you
+will permit the peer to override the entry of the node number.
+.TP
+.B ipxcp-accept-network
+Accept the peer's NAK for the network number specified in the
+ipx-network option. If a network number was specified, and non-zero, the
+default is to insist that the value be used. If you include this
+option then you will permit the peer to override the entry of the node
+number.
+.TP
+.B ipxcp-accept-remote
+Use the peer's network number specified in the configure request
+frame. If a node number was specified for the peer and this option was
+not specified, the peer will be forced to use the value which you have
+specified.
+.TP
+.B ipxcp-max-configure \fIn
+Set the maximum number of IPXCP configure request frames which the
+system will send to \fIn\fR. The default is 10.
+.TP
+.B ipxcp-max-failure \fIn
+Set the maximum number of IPXCP NAK frames which the local system will
+send before it rejects the options. The default value is 3.
+.TP
+.B ipxcp-max-terminate \fIn
+Set the maximum 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<addr>
+If pppd is acting as a server for Microsoft Windows clients, this
+option allows pppd to supply one or two DNS (Domain Name Server)
+addresses to the clients. The first instance of this option specifies
+the primary DNS address; the second instance (if given) specifies the
+secondary DNS address. (This option was present in some older
+versions of pppd under the name \fBdns-addr\fR.)
+.TP
+.B ms-wins \fI<addr>
+If pppd is acting as a server for Microsoft Windows or "Samba"
+clients, this option allows pppd to supply one or two WINS (Windows
+Internet Name Services) server addresses to the clients. The first
+instance of this option specifies the primary WINS address; the second
+instance (if given) specifies the secondary WINS address.
+.TP
+.B name \fIname
+Set the name of the local system for authentication purposes to
+\fIname\fR. This is a privileged option. With this option, pppd will
+use lines in the secrets files which have \fIname\fR as the second
+field when looking for a secret to use in authenticating the peer. In
+addition, unless overridden with the \fIuser\fR option, \fIname\fR
+will be used as the name to send to the peer when authenticating the
+local system to the peer. (Note that pppd does not append the domain
+name to \fIname\fR.)
+.TP
+.B netmask \fIn
+Set the interface netmask to \fIn\fR, a 32 bit netmask in "decimal dot"
+notation (e.g. 255.255.255.0). If this option is given, the value
+specified is ORed with the default netmask. The default netmask is
+chosen based on the negotiated remote IP address; it is the
+appropriate network mask for the class of the remote IP address, ORed
+with the netmasks for any non point-to-point network interfaces in the
+system which are on the same network. (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/cpukit/pppd/pppd.h b/cpukit/pppd/pppd.h
index b33b6a32de..e30ddfe55e 100644
--- a/cpukit/pppd/pppd.h
+++ b/cpukit/pppd/pppd.h
@@ -26,20 +26,25 @@
#ifndef __PPPD_H__
#define __PPPD_H__
-#include <rtems.h>
#include <stdio.h> /* for FILE */
+#include <limits.h> /* for NGROUPS_MAX */
#include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */
#include <sys/types.h> /* for u_int32_t, if defined */
#include <sys/time.h> /* for struct timeval */
#include <net/ppp_defs.h>
-#if __STDC__
+#if defined(__STDC__)
#include <stdarg.h>
#define __V(x) x
#else
#include <varargs.h>
#define __V(x) (va_alist) va_dcl
#define const
+#define volatile
+#endif
+
+#ifdef INET6
+#include "eui64.h"
#endif
/*
@@ -53,11 +58,91 @@
#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/cpukit/pppd/rtemsmain.c b/cpukit/pppd/rtemsmain.c
new file mode 100644
index 0000000000..5a266a9ff3
--- /dev/null
+++ b/cpukit/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 <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+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/cpukit/pppd/rtemspppd.c b/cpukit/pppd/rtemspppd.c
new file mode 100644
index 0000000000..5a821cdfaf
--- /dev/null
+++ b/cpukit/pppd/rtemspppd.c
@@ -0,0 +1,173 @@
+
+#include <rtems.h>
+#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/cpukit/pppd/rtemspppd.h b/cpukit/pppd/rtemspppd.h
new file mode 100644
index 0000000000..9d44e58594
--- /dev/null
+++ b/cpukit/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/cpukit/pppd/sys-rtems.c b/cpukit/pppd/sys-rtems.c
new file mode 100644
index 0000000000..bfc80d50a6
--- /dev/null
+++ b/cpukit/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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
+
+#include <net/if.h>
+#include <net/ppp_defs.h>
+#include <net/if_ppp.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+
+#if RTM_VERSION >= 3
+#include <sys/param.h>
+#if defined(NetBSD) && (NetBSD >= 199703)
+#include <netinet/if_inarp.h>
+#else /* NetBSD 1.2D or later */
+#include <netinet/if_ether.h>
+#endif
+#endif
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/termiostypes.h>
+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/cpukit/pppd/upap.c b/cpukit/pppd/upap.c
index c3c6cf1d6d..b782f26358 100644
--- a/cpukit/pppd/upap.c
+++ b/cpukit/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 <stdio.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
#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, "<hidden>");
break;
case UPAP_AUTHACK:
case UPAP_AUTHNAK:
diff --git a/cpukit/pppd/upap.h b/cpukit/pppd/upap.h
index 510efa3151..42d6f4f0f6 100644
--- a/cpukit/pppd/upap.h
+++ b/cpukit/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/cpukit/pppd/utils.c b/cpukit/pppd/utils.c
new file mode 100644
index 0000000000..b1bdb5d754
--- /dev/null
+++ b/cpukit/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 <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef SVR4
+#include <sys/mkdev.h>
+#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;
+ }
+}
+