*/
#ifndef lint
-static char rcsid[] = "$Id: auth.c,v 1.53 1999/05/13 00:33:05 paulus Exp $";
+static char rcsid[] = "$Id: auth.c,v 1.54 1999/07/21 00:24:30 paulus Exp $";
#endif
#include <stdio.h>
#endif
#include "pathnames.h"
-/* Used for storing a sequence of words. Usually malloced. */
-struct wordlist {
- struct wordlist *next;
- char *word;
-};
-
/* Bits in scan_authfile return value */
#define NONWILD_SERVER 1
#define NONWILD_CLIENT 2
/* List of addresses which the peer may use. */
static struct permitted_ip *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;
}
#endif
+ /*
+ * 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()
+{
phase = PHASE_NETWORK;
#if 0
if (!demand)
/*
* At this point we consider that the link has come up successfully.
*/
- need_holdoff = 0;
status = EXIT_OK;
if (idle_time_limit > 0)
/* link is idle: shut it down. */
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);
/*
* 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)
int unit;
struct wordlist *addrs;
{
- int n = 0;
- struct wordlist *ap;
+ int n;
+ struct wordlist *ap, **pap;
struct permitted_ip *ip;
char *ptr_word, *ptr_mask;
struct hostent *hp;
if (addresses[unit] != NULL)
free(addresses[unit]);
addresses[unit] = NULL;
+ if (extra_options != NULL)
+ free_wordlist(extra_options);
+ extra_options = NULL;
- for (ap = addrs; ap != NULL; ap = ap->next)
- ++n;
+ /*
+ * Count the number of IP addresses given, and chop off
+ * any extra options for this peer.
+ */
+ for (n = 0, pap = &addrs; (ap = *pap) != NULL; pap = &ap->next, ++n) {
+ if (strcmp(ap->word, "--") == 0) {
+ /* rest are options */
+ *pap = 0;
+ extra_options = ap->next;
+ free(ap);
+ break;
+ }
+ }
if (n == 0)
return;
ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip));
*/
#ifndef lint
-static char rcsid[] = "$Id: cbcp.c,v 1.7 1999/05/12 06:19:46 paulus Exp $";
+static char rcsid[] = "$Id: cbcp.c,v 1.8 1999/07/21 00:24:30 paulus Exp $";
#endif
#include <stdio.h>
#include "cbcp.h"
#include "fsm.h"
#include "lcp.h"
-#include "ipcp.h"
/*
* Options.
PUTCHAR(len , bufp);
PUTCHAR(0, bufp);
cbcp_send(us, CBCP_RESP, buf, len);
- (*ipcp_protent.open)(us->us_unit);
+ start_networks();
return;
}
}
*/
#ifndef lint
-static char rcsid[] = "$Id: main.c,v 1.79 1999/05/13 00:35:23 paulus Exp $";
+static char rcsid[] = "$Id: main.c,v 1.80 1999/07/21 00:24:31 paulus Exp $";
#endif
#include <stdio.h>
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 */
static int fd_ppp = -1; /* fd for talking PPP */
* The per-tty options file should not change
* ptycommand, notty or devnam.
*/
+ devnam_fixed = 1;
if (!using_pty) {
- int save_defdev = default_device;
-
- default_device = 1;
if (!options_for_tty())
exit(EXIT_OPTION_ERROR);
- if (notty || ptycommand != NULL) {
- option_error("%s option may not be used in per-tty options file",
- notty? "notty": "pty");
- exit(EXIT_OPTION_ERROR);
- }
- if (!default_device) {
- option_error("per-tty options file may not specify device name");
- exit(EXIT_OPTION_ERROR);
- }
- default_device = save_defdev;
}
+ devnam_fixed = 0;
if (!parse_args(argc-1, argv+1))
exit(EXIT_OPTION_ERROR);
info("Starting link");
}
+ phase = PHASE_SERIALCONN;
+
/*
* Get a pty master/slave pair if the pty, notty, or record
* options were specified.
/*
* Set line speed, flow control, etc.
- * If we have a non-null connection script,
+ * 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
* 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));
+ set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0)
+ || initializer != NULL));
real_ttyfd = ttyfd;
}
}
/* run connection script */
- if (connector && connector[0]) {
- MAINDEBUG(("Connecting with <%s>", connector));
-
+ if ((connector && connector[0]) || initializer) {
if (real_ttyfd != -1) {
if (!default_device && modem) {
setdtr(real_ttyfd, 0); /* in case modem is off hook */
}
}
- if (device_script(connector, ttyfd, ttyfd, 0) < 0) {
- error("Connect script failed");
- status = EXIT_CONNECT_FAILED;
- goto fail;
+ 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 (kill_link)
- goto disconnect;
- info("Serial connection established.");
+ 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 */
}
/* Wait for scripts to finish */
+ /* XXX should have a timeout here */
while (n_children > 0) {
if (debug) {
struct subprocess *chp;
*/
#ifndef lint
-static char rcsid[] = "$Id: options.c,v 1.59 1999/05/14 01:09:03 paulus Exp $";
+static char rcsid[] = "$Id: options.c,v 1.60 1999/07/21 00:24:31 paulus Exp $";
#endif
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <termios.h>
#include <syslog.h>
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 *connector = NULL; /* Script to establish physical link */
char *disconnector = NULL; /* Script to disestablish physical link */
char *welcomer = NULL; /* Script to run after phys link estab. */
extern struct stat devstat;
extern int prepass; /* Doing pre-pass to find device name */
+struct option_info initializer_info;
struct option_info connector_info;
struct option_info disconnector_info;
struct option_info welcomer_info;
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
static int showversion __P((char **));
static int showhelp __P((char **));
static void usage __P((void));
+static int setlogfile __P((char **));
#ifdef PPP_FILTER
static int setpassfilter __P((char **));
"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, &connector,
"A program to set up a connection",
OPT_A2INFO | OPT_PRIVFIX, &connector_info },
OPT_A2INFO | OPT_PRIVFIX, &welcomer_info },
{ "pty", o_string, &ptycommand,
"Script to run on pseudo-tty master side",
- OPT_A2INFO | OPT_PRIVFIX | OPT_PREPASS, &ptycommand_info },
+ OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info },
{ "notty", o_bool, ¬ty,
- "Input/output is not a tty", OPT_PREPASS | 1 },
+ "Input/output is not a tty", OPT_DEVNAM | 1 },
{ "record", o_string, &record_file,
"Record characters sent/received to file" },
{ "maxconnect", o_int, &maxconnect,
{ "nopersist", o_bool, &persist,
"Turn off persist option" },
{ "demand", o_bool, &demand,
- "Dial on demand", 1, &persist },
+ "Dial on demand", OPT_INITONLY | 1, &persist },
{ "--version", o_special_noarg, showversion,
"Show version number" },
{ "--help", o_special_noarg, showhelp,
"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) },
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;
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;
+ 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;
+ }
+ ret = 1;
+
+err:
+ return ret;
+}
+
/*
* find_option - scan the option lists for the various protocols
* looking for an entry with the given name.
char *sv;
int (*parser) __P((char **));
- if (prepass && (opt->flags & OPT_PREPASS) == 0)
+ 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;
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;
crtscts = -2;
return (1);
}
+
+static int
+setlogfile(argv)
+ char **argv;
+{
+ int fd, err;
+
+ if (!privileged_option)
+ seteuid(getuid());
+ fd = open(*argv, O_WRONLY | O_APPEND);
+ err = errno;
+ if (!privileged_option)
+ seteuid(0);
+ 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;
+}
.\" manual page [] for pppd 2.3
-.\" $Id: pppd.8,v 1.40 1999/05/13 00:34:04 paulus Exp $
+.\" $Id: pppd.8,v 1.41 1999/07/21 00:24:32 paulus Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
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.
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.
.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
required if the peer is buggy and gets confused by requests from pppd
for IPXCP negotiation.
.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
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.
+.TP
.B user \fIname
Sets the name used for authenticating the local system to the peer to
\fIname\fR.
.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).
.SH SCRIPTS
Pppd invokes scripts at various stages in its processing which can be
used to perform site-specific ancillary processing. These scripts are
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $Id: pppd.h,v 1.41 1999/05/14 01:09:03 paulus Exp $
+ * $Id: pppd.h,v 1.42 1999/07/21 00:24:32 paulus Exp $
*/
/*
#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_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)
unsigned int bytes_out;
};
+/* Used for storing a sequence of words. Usually malloced. */
+struct wordlist {
+ struct wordlist *next;
+ char *word;
+};
+
/*
* Global variables.
*/
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 */
/*
* Variables set by command-line options.
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 *connector; /* Script to establish physical link */
extern char *disconnector; /* Script to disestablish physical link */
extern char *welcomer; /* Script to welcome client after connection */
*/
#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_TERMINATE 8
+#define PHASE_HOLDOFF 9
/*
* The following struct gives the addresses of procedures to call
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 */
/* 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, ...));
};
extern struct option_info devnam_info;
+extern struct option_info initializer_info;
extern struct option_info connector_info;
extern struct option_info disconnector_info;
extern struct option_info welcomer_info;
#define EXIT_PEER_DEAD 15
#define EXIT_HANGUP 16
#define EXIT_LOOPBACK 17
+#define EXIT_INIT_FAILED 18
/*
* Debug macros. Slightly useful for finding bugs in pppd, not particularly