summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-03-21 15:19:13 +0000
committerpeter <peter@FreeBSD.org>1998-03-21 15:19:13 +0000
commit1d53c0aa7cae24c699b13969c4b8857c268bc6fe (patch)
treebb5e2d1860216026d60021f2edb52090ea0cffd7
parent2930d5cccfe9da0a05b1291f9d0bde64ac873749 (diff)
downloadFreeBSD-src-1d53c0aa7cae24c699b13969c4b8857c268bc6fe.zip
FreeBSD-src-1d53c0aa7cae24c699b13969c4b8857c268bc6fe.tar.gz
Import ppp-2.3.3 onto vendor branch.
Obtained from: ftp://cs.anu.edu.au/pub/software/ppp
-rw-r--r--usr.sbin/pppd/demand.c4
-rw-r--r--usr.sbin/pppd/main.c1947
-rw-r--r--usr.sbin/pppd/options.c1809
-rw-r--r--usr.sbin/pppd/sys-bsd.c998
4 files changed, 3351 insertions, 1407 deletions
diff --git a/usr.sbin/pppd/demand.c b/usr.sbin/pppd/demand.c
index dc13ba7..cbd8980 100644
--- a/usr.sbin/pppd/demand.c
+++ b/usr.sbin/pppd/demand.c
@@ -18,7 +18,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: demand.c,v 1.6 1997/04/30 05:51:56 paulus Exp $";
+static char rcsid[] = "$Id: demand.c,v 1.7 1997/11/27 06:08:26 paulus Exp $";
#endif
#include <stdio.h>
@@ -35,8 +35,8 @@ static char rcsid[] = "$Id: demand.c,v 1.6 1997/04/30 05:51:56 paulus Exp $";
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
-#include <net/if.h>
#ifdef PPP_FILTER
+#include <net/if.h>
#include <net/bpf.h>
#include <pcap.h>
#endif
diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c
index 1e1397e..934827d 100644
--- a/usr.sbin/pppd/main.c
+++ b/usr.sbin/pppd/main.c
@@ -18,13 +18,14 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: main.c,v 1.13 1994/05/27 01:02:14 paulus Exp $";
+static char rcsid[] = "$Id: main.c,v 1.43 1997/11/27 06:09:20 paulus Exp $";
#endif
-#define SETSID
-
#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
@@ -32,228 +33,236 @@ static char rcsid[] = "$Id: main.c,v 1.13 1994/05/27 01:02:14 paulus Exp $";
#include <netdb.h>
#include <utmp.h>
#include <pwd.h>
-#include <sys/wait.h>
-
-/*
- * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless
- * /etc/ppp/options exists.
- */
-#ifndef REQ_SYSOPTIONS
-#define REQ_SYSOPTIONS 1
-#endif
-
-#ifdef SGTTY
-#include <sgtty.h>
-#else
-#ifndef sun
-#include <sys/ioctl.h>
-#endif
-#include <termios.h>
-#endif
-
#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 <sys/time.h>
-#include <net/if.h>
-#include "callout.h"
-#include "ppp.h"
+#include "pppd.h"
#include "magic.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
#include "upap.h"
#include "chap.h"
-
-#include "pppd.h"
+#include "ccp.h"
#include "pathnames.h"
#include "patchlevel.h"
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
-#ifndef TRUE
-#define TRUE (1)
-#endif /*TRUE*/
-
-#ifndef FALSE
-#define FALSE (0)
-#endif /*FALSE*/
+#if defined(SUNOS4)
+extern char *strerror();
+#endif
-#ifdef PIDPATH
-static char *pidpath = PIDPATH; /* filename in which pid will be stored */
-#else
-static char *pidpath = _PATH_PIDFILE;
-#endif /* PIDFILE */
+#ifdef IPX_CHANGE
+#include "ipxcp.h"
+#endif /* IPX_CHANGE */
+#ifdef AT_CHANGE
+#include "atcp.h"
+#endif
/* interface vars */
-char ifname[IFNAMSIZ]; /* Interface name */
+char ifname[32]; /* Interface name */
int ifunit; /* Interface unit number */
char *progname; /* Name of this program */
char hostname[MAXNAMELEN]; /* Our hostname */
-char our_name[MAXNAMELEN];
-char remote_name[MAXNAMELEN];
-static char pidfilename[MAXPATHLEN];
-
-static pid_t pid; /* Our pid */
-static pid_t pgrpid; /* Process Group ID */
-uid_t uid; /* Our real user-id */
-
-char devname[MAXPATHLEN] = "/dev/tty"; /* Device name */
-int default_device = TRUE; /* use default device (stdin/out) */
-
-int fd = -1; /* Device file descriptor */
-int s; /* Socket file descriptor */
+static char pidfilename[MAXPATHLEN]; /* name of pid file */
+static char default_devnam[MAXPATHLEN]; /* name of default device */
+static pid_t pid; /* Our pid */
+static uid_t uid; /* Our real user-id */
+static int conn_running; /* we have a [dis]connector running */
+
+int ttyfd = -1; /* Serial port file descriptor */
+mode_t tty_mode = -1; /* Original access permissions to tty */
+int baud_rate; /* Actual bits/second for serial device */
+int hungup; /* terminal has been hung up */
+int privileged; /* we're running as real uid root */
+int need_holdoff; /* need holdoff period before restarting */
int phase; /* where the link is at */
+int kill_link;
+int open_ccp_flag;
+int redirect_stderr; /* Connector's stderr should go to file */
-#ifdef SGTTY
-static struct sgttyb initsgttyb; /* Initial TTY sgttyb */
-#else
-static struct termios inittermios; /* Initial TTY termios */
-#endif
+u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
+u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
-static int initfdflags = -1; /* Initial file descriptor flags */
-
-static int restore_term; /* 1 => we've munged the terminal */
+static int n_children; /* # child processes still running */
-u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */
-static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* buffer for incoming packet */
+static int locked; /* lock() has succeeded */
+
+char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
+
+/* Prototypes for procedures local to this file. */
+
+static void 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 kill_my_pg __P((int));
+static void hup __P((int));
+static void term __P((int));
+static void chld __P((int));
+static void toggle_debug __P((int));
+static void open_ccp __P((int));
+static void bad_signal __P((int));
+static void holdoff_end __P((void *));
+static int device_script __P((char *, int, int));
+static void reap_kids __P((void));
+static void pr_log __P((void *, char *, ...));
+
+extern char *ttyname __P((int));
+extern char *getlogin __P((void));
+int main __P((int, char *[]));
-int hungup; /* terminal has been hung up */
-static int n_children; /* # child processes still running */
+#ifdef ultrix
+#undef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
-/* configured variables */
-
-int debug = 0; /* Debug flag */
-int kdebugflag = 0; /* Kernel debugging flag */
-char user[MAXNAMELEN]; /* username for PAP */
-char passwd[MAXSECRETLEN]; /* password for PAP */
-char *connector = NULL; /* "connect" command */
-char *disconnector = NULL; /* "disconnect" command */
-int inspeed = 0; /* Input/Output speed requested */
-int baud_rate; /* bits/sec currently used */
-u_long netmask = 0; /* netmask to use on ppp interface */
-int crtscts = 0; /* use h/w flow control */
-int nodetach = 0; /* don't fork */
-int modem = 0; /* use modem control lines */
-int auth_required = 0; /* require peer to authenticate */
-int defaultroute = 0; /* assign default route through interface */
-int proxyarp = 0; /* set entry in arp table */
-int persist = 0; /* re-initiate on termination */
-int answer = 0; /* wait for incoming call */
-int uselogin = 0; /* check PAP info against /etc/passwd */
-int lockflag = 0; /* lock the serial device */
-
-
-/* prototypes */
-static void hup __ARGS((int));
-static void intr __ARGS((int));
-static void term __ARGS((int));
-static void alrm __ARGS((int));
-static void io __ARGS((int));
-static void chld __ARGS((int));
-static void incdebug __ARGS((int));
-static void nodebug __ARGS((int));
-void establish_ppp __ARGS((void));
-
-void reap_kids __ARGS((void));
-void cleanup __ARGS((int, caddr_t));
-void die __ARGS((int));
-void novm __ARGS((char *));
-
-void log_packet __ARGS((u_char *, int, char *));
-void format_packet __ARGS((u_char *, int,
- void (*) (void *, char *, ...), void *));
-void pr_log __ARGS((void *, char *, ...));
-
-extern char *ttyname __ARGS((int));
-extern char *getlogin __ARGS((void));
+#ifdef ULTRIX
+#define setlogmask(x)
+#endif
/*
* PPP Data Link Layer "protocol" table.
* One entry per supported protocol.
+ * The last entry must be NULL.
*/
-static struct protent {
- u_short protocol;
- void (*init)();
- void (*input)();
- void (*protrej)();
- int (*printpkt)();
- char *name;
-} prottbl[] = {
- { LCP, lcp_init, lcp_input, lcp_protrej, lcp_printpkt, "LCP" },
- { IPCP, ipcp_init, ipcp_input, ipcp_protrej, ipcp_printpkt, "IPCP" },
- { UPAP, upap_init, upap_input, upap_protrej, upap_printpkt, "PAP" },
- { CHAP, ChapInit, ChapInput, ChapProtocolReject, ChapPrintPkt, "CHAP" },
+struct protent *protocols[] = {
+ &lcp_protent,
+ &pap_protent,
+ &chap_protent,
+#ifdef CBCP_SUPPORT
+ &cbcp_protent,
+#endif
+ &ipcp_protent,
+ &ccp_protent,
+#ifdef IPX_CHANGE
+ &ipxcp_protent,
+#endif
+#ifdef AT_CHANGE
+ &atcp_protent,
+#endif
+ NULL
};
-#define N_PROTO (sizeof(prottbl) / sizeof(prottbl[0]))
-
+int
main(argc, argv)
int argc;
char *argv[];
{
- int mask, i;
+ int i, fdflags;
struct sigaction sa;
- struct cmd *cmdp;
FILE *pidfile;
char *p;
struct passwd *pw;
+ struct timeval timo;
+ sigset_t mask;
+ struct protent *protp;
+ struct stat statbuf;
+ phase = PHASE_INITIALIZE;
p = ttyname(0);
if (p)
- strcpy(devname, p);
-
+ strcpy(devnam, p);
+ strcpy(default_devnam, devnam);
+
+ /* Initialize syslog facilities */
+#ifdef ULTRIX
+ openlog("pppd", LOG_PID);
+#else
+ openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
+ setlogmask(LOG_UPTO(LOG_INFO));
+#endif
+
if (gethostname(hostname, MAXNAMELEN) < 0 ) {
- perror("couldn't get hostname");
+ option_error("Couldn't get hostname: %m");
die(1);
}
hostname[MAXNAMELEN-1] = 0;
- pid = getpid();
uid = getuid();
-
- if (!ppp_available()) {
- fprintf(stderr, "Sorry - PPP is not available on this system\n");
- exit(1);
- }
+ privileged = uid == 0;
/*
* Initialize to the standard option set, then parse, in order,
- * the system options file, the user's options file, and the command
- * line arguments.
+ * the system options file, the user's options file,
+ * the tty's options file, and the command line arguments.
*/
- for (i = 0; i < N_PROTO; i++)
- (*prottbl[i].init)(0);
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ (*protp->init)(0);
progname = *argv;
- if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) ||
- !options_from_user() ||
- !parse_args(argc-1, argv+1) ||
- !options_for_tty())
+ if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
+ || !options_from_user())
+ exit(1);
+ scan_args(argc-1, argv+1); /* look for tty name on command line */
+ if (!options_for_tty()
+ || !parse_args(argc-1, argv+1))
+ exit(1);
+
+ /*
+ * Check that we are running as root.
+ */
+ if (geteuid() != 0) {
+ option_error("must be root to run %s, since it is not setuid-root",
+ argv[0]);
die(1);
- check_auth_options();
- setipdefault();
+ }
+
+ if (!ppp_available()) {
+ option_error(no_ppp_msg);
+ exit(1);
+ }
/*
- * Initialize syslog system and magic number package.
+ * Check that the options given are valid and consistent.
*/
-#if !defined(ultrix)
- openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
- setlogmask(LOG_UPTO(LOG_INFO));
-#else
- openlog("pppd", LOG_PID);
-#define LOG_UPTO(x) (x)
-#define setlogmask(x) (x)
-#endif
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
+ sys_check_options();
+ auth_check_options();
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->check_options != NULL)
+ (*protp->check_options)();
+ if (demand && connector == 0) {
+ option_error("connect script required for demand-dialling\n");
+ exit(1);
+ }
+
+ /*
+ * If the user has specified the default device name explicitly,
+ * pretend they hadn't.
+ */
+ if (!default_device && strcmp(devnam, default_devnam) == 0)
+ default_device = 1;
+ redirect_stderr = !nodetach || default_device;
+ /*
+ * Initialize system-dependent stuff and magic number package.
+ */
+ sys_init();
magic_init();
+ if (debug)
+ setlogmask(LOG_UPTO(LOG_DEBUG));
+ /*
+ * Detach ourselves from the terminal, if required,
+ * and identify who is running us.
+ */
+ if (!default_device && !nodetach && daemon(0, 0) < 0) {
+ perror("Couldn't detach from controlling terminal");
+ exit(1);
+ }
+ pid = getpid();
p = getlogin();
if (p == NULL) {
pw = getpwuid(uid);
@@ -262,65 +271,8 @@ main(argc, argv)
else
p = "(unknown)";
}
- syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d",
- VERSION, PATCHLEVEL, p, uid);
-
-#ifdef SETSID
- /*
- * Make sure we can set the serial device to be our controlling terminal.
- */
- if (default_device) {
- /*
- * No device name was specified:
- * we are in the device's session already.
- */
- if ((pgrpid = getpgrp(0)) < 0) {
- syslog(LOG_ERR, "getpgrp(0): %m");
- die(1);
- }
-
- } else {
- /*
- * Not default device: make sure we're not a process group leader,
- * then become session leader of a new session (so we can make
- * our device its controlling terminal and thus get SIGHUPs).
- */
- if (!nodetach) {
- /* fork so we're not a process group leader */
- if (pid = fork()) {
- exit(0); /* parent is finished */
- }
- if (pid < 0) {
- syslog(LOG_ERR, "fork: %m");
- die(1);
- }
- pid = getpid(); /* otherwise pid is 0 in child */
- } else {
- /*
- * try to put ourself into our parent's process group,
- * so we're not a process group leader
- */
- if (setpgrp(pid, getppid()) < 0)
- syslog(LOG_WARNING, "setpgrp: %m");
- }
-
- /* create new session */
- if ((pgrpid = setsid()) < 0) {
- syslog(LOG_ERR, "setsid(): %m");
- die(1);
- }
- }
-#endif
-
- if (lockflag && !default_device)
- if (lock(devname) < 0)
- die(1);
-
- /* Get an internet socket for doing socket ioctl's on. */
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "socket : %m");
- die(1);
- }
+ syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d",
+ VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);
/*
* Compute mask of all interesting signals and install signal handlers
@@ -330,17 +282,13 @@ main(argc, argv)
sigemptyset(&mask);
sigaddset(&mask, SIGHUP);
sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGALRM);
- sigaddset(&mask, SIGIO);
+ sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGCHLD);
-#ifdef STREAMS
- sigaddset(&mask, SIGPOLL);
-#endif
#define SIGNAL(s, handler) { \
sa.sa_handler = handler; \
if (sigaction(s, &sa, NULL) < 0) { \
- syslog(LOG_ERR, "sigaction(%d): %m", s); \
+ syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
die(1); \
} \
}
@@ -348,393 +296,416 @@ main(argc, argv)
sa.sa_mask = mask;
sa.sa_flags = 0;
SIGNAL(SIGHUP, hup); /* Hangup */
- SIGNAL(SIGINT, intr); /* Interrupt */
+ SIGNAL(SIGINT, term); /* Interrupt */
SIGNAL(SIGTERM, term); /* Terminate */
- SIGNAL(SIGALRM, alrm); /* Timeout */
- SIGNAL(SIGIO, io); /* Input available */
- SIGNAL(SIGCHLD, chld); /* Death of child process */
-#ifdef STREAMS
- SIGNAL(SIGPOLL, io); /* Input available */
-#endif
+ SIGNAL(SIGCHLD, chld);
- signal(SIGUSR1, incdebug); /* Increment debug flag */
- signal(SIGUSR2, nodebug); /* Reset debug flag */
+ SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */
+ SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */
/*
- * Block SIGIOs and SIGPOLLs for now
+ * Install a handler for other signals which would otherwise
+ * cause pppd to exit without cleaning up.
*/
- sigemptyset(&mask);
- sigaddset(&mask, SIGIO);
-#ifdef STREAMS
- sigaddset(&mask, SIGPOLL);
+ SIGNAL(SIGABRT, bad_signal);
+ SIGNAL(SIGALRM, bad_signal);
+ SIGNAL(SIGFPE, bad_signal);
+ SIGNAL(SIGILL, bad_signal);
+ SIGNAL(SIGPIPE, bad_signal);
+ SIGNAL(SIGQUIT, bad_signal);
+ SIGNAL(SIGSEGV, bad_signal);
+#ifdef SIGBUS
+ SIGNAL(SIGBUS, bad_signal);
+#endif
+#ifdef SIGEMT
+ SIGNAL(SIGEMT, bad_signal);
+#endif
+#ifdef SIGPOLL
+ SIGNAL(SIGPOLL, bad_signal);
+#endif
+#ifdef SIGPROF
+ SIGNAL(SIGPROF, bad_signal);
+#endif
+#ifdef SIGSYS
+ SIGNAL(SIGSYS, bad_signal);
+#endif
+#ifdef SIGTRAP
+ SIGNAL(SIGTRAP, bad_signal);
+#endif
+#ifdef SIGVTALRM
+ SIGNAL(SIGVTALRM, bad_signal);
+#endif
+#ifdef SIGXCPU
+ SIGNAL(SIGXCPU, bad_signal);
+#endif
+#ifdef SIGXFSZ
+ SIGNAL(SIGXFSZ, bad_signal);
#endif
- sigprocmask(SIG_BLOCK, &mask, NULL);
/*
- * Open the serial device and set it up to be the ppp interface.
+ * Apparently we can get a SIGPIPE when we call syslog, if
+ * syslogd has died and been restarted. Ignoring it seems
+ * be sufficient.
*/
- if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) {
- syslog(LOG_ERR, "open(%s): %m", devname);
- die(1);
- }
- hungup = 0;
+ signal(SIGPIPE, SIG_IGN);
-#ifdef TIOCSCTTY
- /* set device to be controlling tty */
- if (!default_device && ioctl(fd, TIOCSCTTY) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSCTTY): %m");
- die(1);
+ /*
+ * If we're doing dial-on-demand, set up the interface now.
+ */
+ if (demand) {
+ /*
+ * Open the loopback channel and set it up to be the ppp interface.
+ */
+ open_ppp_loopback();
+
+ syslog(LOG_INFO, "Using interface ppp%d", ifunit);
+ (void) sprintf(ifname, "ppp%d", ifunit);
+
+ /* write pid to file */
+ (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
+ if ((pidfile = fopen(pidfilename, "w")) != NULL) {
+ fprintf(pidfile, "%d\n", pid);
+ (void) fclose(pidfile);
+ } else {
+ syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename);
+ pidfilename[0] = 0;
+ }
+
+ /*
+ * Configure the interface and mark it up, etc.
+ */
+ demand_conf();
}
-#endif /* TIOCSCTTY */
- /* run connection script */
- if (connector) {
- MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
+ for (;;) {
- /* set line speed, flow control, etc.; set CLOCAL for now */
- set_up_tty(fd, 1);
+ need_holdoff = 1;
- /* drop dtr to hang up in case modem is off hook */
- if (!default_device && modem) {
- setdtr(fd, FALSE);
- sleep(1);
- setdtr(fd, TRUE);
+ if (demand) {
+ /*
+ * Don't do anything until we see some activity.
+ */
+ phase = PHASE_DORMANT;
+ kill_link = 0;
+ demand_unblock();
+ for (;;) {
+ wait_loop_output(timeleft(&timo));
+ calltimeout();
+ if (kill_link) {
+ if (!persist)
+ die(0);
+ kill_link = 0;
+ }
+ if (get_loop_output())
+ break;
+ reap_kids();
+ }
+
+ /*
+ * Now we want to bring up the link.
+ */
+ demand_block();
+ syslog(LOG_INFO, "Starting link");
}
- if (device_script(connector, fd, fd) < 0) {
- syslog(LOG_ERR, "could not set up connection");
- setdtr(fd, FALSE);
- die(1);
+ /*
+ * Lock the device if we've been asked to.
+ */
+ if (lockflag && !default_device) {
+ if (lock(devnam) < 0)
+ goto fail;
+ locked = 1;
}
- syslog(LOG_INFO, "Connected...");
- sleep(1); /* give it time to set up its terminal */
- }
-
- /* set line speed, flow control, etc.; clear CLOCAL if modem option */
- set_up_tty(fd, 0);
+ /*
+ * Open the serial device and set it up to be the ppp interface.
+ * First we open it in non-blocking mode so we can set the
+ * various termios flags appropriately. If we aren't dialling
+ * out and we want to use the modem lines, we reopen it later
+ * in order to wait for the carrier detect signal from the modem.
+ */
+ while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) {
+ if (errno != EINTR)
+ syslog(LOG_ERR, "Failed to open %s: %m", devnam);
+ if (!persist || errno != EINTR)
+ goto fail;
+ }
+ if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
+ || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
+ syslog(LOG_WARNING,
+ "Couldn't reset non-blocking mode on device: %m");
+
+ hungup = 0;
+ kill_link = 0;
- /* set up the serial device as a ppp interface */
- establish_ppp();
+ /*
+ * Do the equivalent of `mesg n' to stop broadcast messages.
+ */
+ if (fstat(ttyfd, &statbuf) < 0
+ || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
+ syslog(LOG_WARNING,
+ "Couldn't restrict write permissions to %s: %m", devnam);
+ } else
+ tty_mode = statbuf.st_mode;
- syslog(LOG_INFO, "Using interface ppp%d", ifunit);
- (void) sprintf(ifname, "ppp%d", ifunit);
+ /* run connection script */
+ if (connector && connector[0]) {
+ MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
- /* write pid to file */
- (void) sprintf(pidfilename, "%s/%s.pid", pidpath, ifname);
- if ((pidfile = fopen(pidfilename, "w")) != NULL) {
- fprintf(pidfile, "%d\n", pid);
- (void) fclose(pidfile);
- } else {
- syslog(LOG_ERR, "unable to create pid file: %m");
- pidfilename[0] = 0;
- }
+ /*
+ * Set line speed, flow control, etc.
+ * On most systems we set CLOCAL for now so that we can talk
+ * to the modem before carrier comes up. But this has the
+ * side effect that we might miss it if CD drops before we
+ * get to clear CLOCAL below. On systems where we can talk
+ * successfully to the modem with CLOCAL clear and CD down,
+ * we can clear CLOCAL at this point.
+ */
+ set_up_tty(ttyfd, 1);
- /*
- * Set process group of device to our process group so we can get
- * SIGIOs and SIGHUPs.
- */
-#ifdef SETSID
- if (default_device) {
- int id = tcgetpgrp(fd);
- if (id != pgrpid) {
- syslog(LOG_WARNING, "warning: not in tty's process group");
+ /* drop dtr to hang up in case modem is off hook */
+ if (!default_device && modem) {
+ setdtr(ttyfd, FALSE);
+ sleep(1);
+ setdtr(ttyfd, TRUE);
+ }
+
+ if (device_script(connector, ttyfd, ttyfd) < 0) {
+ syslog(LOG_ERR, "Connect script failed");
+ setdtr(ttyfd, FALSE);
+ goto fail;
+ }
+
+
+ syslog(LOG_INFO, "Serial connection established.");
+ sleep(1); /* give it time to set up its terminal */
}
- } else {
- if (tcsetpgrp(fd, pgrpid) < 0) {
- syslog(LOG_ERR, "tcsetpgrp(): %m");
- die(1);
+
+ /* set line speed, flow control, etc.; clear CLOCAL if modem option */
+ set_up_tty(ttyfd, 0);
+
+ /* reopen tty if necessary to wait for carrier */
+ if (connector == NULL && modem) {
+ while ((i = open(devnam, O_RDWR)) < 0) {
+ if (errno != EINTR)
+ syslog(LOG_ERR, "Failed to reopen %s: %m", devnam);
+ if (!persist || errno != EINTR || hungup || kill_link)
+ goto fail;
+ }
+ close(i);
}
- }
-#else
- /* set process group on tty so we get SIGIO's */
- if (ioctl(fd, TIOCSPGRP, &pgrpid) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSPGRP): %m");
- die(1);
- }
-#endif
- /*
- * Record initial device flags, then set device to cause SIGIO
- * signals to be generated.
- */
- if ((initfdflags = fcntl(fd, F_GETFL)) == -1) {
- syslog(LOG_ERR, "fcntl(F_GETFL): %m");
- die(1);
- }
+ /* run welcome script, if any */
+ if (welcomer && welcomer[0]) {
+ if (device_script(welcomer, ttyfd, ttyfd) < 0)
+ syslog(LOG_WARNING, "Welcome script failed");
+ }
-#ifdef _linux_ /* This is a kludge for Linux. FIXME !!! -- later. */
-#undef FASYNC
-#define FASYNC 0
-#endif
+ /* set up the serial device as a ppp interface */
+ establish_ppp(ttyfd);
+
+ if (!demand) {
+
+ syslog(LOG_INFO, "Using interface ppp%d", ifunit);
+ (void) sprintf(ifname, "ppp%d", ifunit);
+
+ /* write pid to file */
+ (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
+ if ((pidfile = fopen(pidfilename, "w")) != NULL) {
+ fprintf(pidfile, "%d\n", pid);
+ (void) fclose(pidfile);
+ } else {
+ syslog(LOG_ERR, "Failed to create pid file %s: %m",
+ pidfilename);
+ pidfilename[0] = 0;
+ }
+ }
- if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) {
- syslog(LOG_ERR, "fcntl(F_SETFL, FNDELAY | FASYNC): %m");
- die(1);
- }
-
- /*
- * Block all signals, start opening the connection, and wait for
- * incoming signals (reply, timeout, etc.).
- */
- syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devname);
- sigprocmask(SIG_BLOCK, &mask, NULL); /* Block signals now */
- lcp_lowerup(0); /* XXX Well, sort of... */
- lcp_open(0); /* Start protocol */
- for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; )
- sigpause(0); /* Wait for next signal */
+ /*
+ * Start opening the connection and wait for
+ * incoming events (reply, timeout, etc.).
+ */
+ syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
+ lcp_lowerup(0);
+ lcp_open(0); /* Start protocol */
+ for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
+ wait_input(timeleft(&timo));
+ calltimeout();
+ get_input();
+ if (kill_link) {
+ lcp_close(0, "User request");
+ kill_link = 0;
+ }
+ if (open_ccp_flag) {
+ if (phase == PHASE_NETWORK) {
+ ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
+ (*ccp_protent.open)(0);
+ }
+ open_ccp_flag = 0;
+ }
+ reap_kids(); /* Don't leave dead kids lying around */
+ }
- /*
- * Run disconnector script, if requested
- */
- if (disconnector) {
- if (device_script(disconnector, fd, fd) < 0) {
- syslog(LOG_WARNING, "disconnect script failed");
- die(1);
+ /*
+ * If we may want to bring the link up again, transfer
+ * the ppp unit back to the loopback. Set the
+ * real serial device back to its normal mode of operation.
+ */
+ clean_check();
+ if (demand)
+ restore_loop();
+ disestablish_ppp(ttyfd);
+
+ /*
+ * Run disconnector script, if requested.
+ * XXX we may not be able to do this if the line has hung up!
+ */
+ if (disconnector && !hungup) {
+ set_up_tty(ttyfd, 1);
+ if (device_script(disconnector, ttyfd, ttyfd) < 0) {
+ syslog(LOG_WARNING, "disconnect script failed");
+ } else {
+ syslog(LOG_INFO, "Serial link disconnected.");
+ }
}
- syslog(LOG_INFO, "Disconnected...");
- }
+ fail:
+ if (ttyfd >= 0)
+ close_tty();
+ if (locked) {
+ unlock();
+ locked = 0;
+ }
- quit();
-}
+ if (!demand) {
+ if (pidfilename[0] != 0
+ && unlink(pidfilename) < 0 && errno != ENOENT)
+ syslog(LOG_WARNING, "unable to delete pid file: %m");
+ pidfilename[0] = 0;
+ }
-#if B9600 == 9600
-/*
- * XXX assume speed_t values numerically equal bits per second
- * (so we can ask for any speed).
- */
-#define translate_speed(bps) (bps)
-#define baud_rate_of(speed) (speed)
+ if (!persist)
+ die(1);
-#else
-/*
- * List of valid speeds.
- */
-struct speed {
- int speed_int, speed_val;
-} speeds[] = {
-#ifdef B50
- { 50, B50 },
-#endif
-#ifdef B75
- { 75, B75 },
-#endif
-#ifdef B110
- { 110, B110 },
-#endif
-#ifdef B134
- { 134, B134 },
-#endif
-#ifdef B150
- { 150, B150 },
-#endif
-#ifdef B200
- { 200, B200 },
-#endif
-#ifdef B300
- { 300, B300 },
-#endif
-#ifdef B600
- { 600, B600 },
-#endif
-#ifdef B1200
- { 1200, B1200 },
-#endif
-#ifdef B1800
- { 1800, B1800 },
-#endif
-#ifdef B2000
- { 2000, B2000 },
-#endif
-#ifdef B2400
- { 2400, B2400 },
-#endif
-#ifdef B3600
- { 3600, B3600 },
-#endif
-#ifdef B4800
- { 4800, B4800 },
-#endif
-#ifdef B7200
- { 7200, B7200 },
-#endif
-#ifdef B9600
- { 9600, B9600 },
-#endif
-#ifdef B19200
- { 19200, B19200 },
-#endif
-#ifdef B38400
- { 38400, B38400 },
-#endif
-#ifdef EXTA
- { 19200, EXTA },
-#endif
-#ifdef EXTB
- { 38400, EXTB },
-#endif
-#ifdef B57600
- { 57600, B57600 },
-#endif
-#ifdef B115200
- { 115200, B115200 },
-#endif
- { 0, 0 }
-};
+ if (demand)
+ demand_discard();
+ if (holdoff > 0 && need_holdoff) {
+ phase = PHASE_HOLDOFF;
+ TIMEOUT(holdoff_end, NULL, holdoff);
+ do {
+ wait_time(timeleft(&timo));
+ calltimeout();
+ if (kill_link) {
+ if (!persist)
+ die(0);
+ kill_link = 0;
+ phase = PHASE_DORMANT; /* allow signal to end holdoff */
+ }
+ reap_kids();
+ } while (phase == PHASE_HOLDOFF);
+ }
+ }
-/*
- * Translate from bits/second to a speed_t.
- */
-int
-translate_speed(bps)
- int bps;
-{
- struct speed *speedp;
-
- if (bps == 0)
- return 0;
- for (speedp = speeds; speedp->speed_int; speedp++)
- if (bps == speedp->speed_int)
- return speedp->speed_val;
- syslog(LOG_WARNING, "speed %d not supported", bps);
+ die(0);
return 0;
}
/*
- * Translate from a speed_t to bits/second.
+ * holdoff_end - called via a timeout when the holdoff period ends.
*/
-int
-baud_rate_of(speed)
- int speed;
+static void
+holdoff_end(arg)
+ void *arg;
{
- struct speed *speedp;
-
- if (speed == 0)
- return 0;
- for (speedp = speeds; speedp->speed_int; speedp++)
- if (speed == speedp->speed_val)
- return speedp->speed_int;
- return 0;
+ phase = PHASE_DORMANT;
}
-#endif
/*
- * 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.
+ * get_input - called when incoming data is available.
*/
-set_up_tty(fd, local)
- int fd, local;
+static void
+get_input()
{
-#ifndef SGTTY
- int speed, x;
- struct termios tios;
+ int len, i;
+ u_char *p;
+ u_short protocol;
+ struct protent *protp;
- if (tcgetattr(fd, &tios) < 0) {
- syslog(LOG_ERR, "tcgetattr: %m");
- die(1);
- }
+ p = inpacket_buf; /* point to beginning of packet buffer */
- if (!restore_term)
- inittermios = tios;
+ len = read_packet(inpacket_buf);
+ if (len < 0)
+ return;
-#ifdef CRTSCTS
- tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL | CRTSCTS);
- if (crtscts == 1)
- tios.c_cflag |= CRTSCTS;
-#else
- tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
-#endif /* CRTSCTS */
-
- tios.c_cflag |= CS8 | CREAD | HUPCL;
- if (local || !modem)
- tios.c_cflag |= CLOCAL;
- tios.c_iflag = IGNBRK | IGNPAR;
- tios.c_oflag = 0;
- tios.c_lflag = 0;
- tios.c_cc[VMIN] = 1;
- tios.c_cc[VTIME] = 0;
-
- if (crtscts == 2) {
- tios.c_iflag |= IXOFF;
- tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
- tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
+ if (len == 0) {
+ syslog(LOG_NOTICE, "Modem hangup");
+ hungup = 1;
+ lcp_lowerdown(0); /* serial link is no longer available */
+ link_terminated(0);
+ return;
}
- speed = translate_speed(inspeed);
- if (speed) {
- cfsetospeed(&tios, speed);
- cfsetispeed(&tios, speed);
- } else {
- speed = cfgetospeed(&tios);
- }
+ if (debug /*&& (debugflags & DBG_INPACKET)*/)
+ log_packet(p, len, "rcvd ", LOG_DEBUG);
- if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
- syslog(LOG_ERR, "tcsetattr: %m");
- die(1);
+ if (len < PPP_HDRLEN) {
+ MAINDEBUG((LOG_INFO, "io(): Received short packet."));
+ return;
}
-#ifdef ultrix
- x = 0;
- if (ioctl(fd, (crtscts || modem)? TIOCMODEM: TIOCNMODEM, &x) < 0)
- syslog(LOG_WARNING, "TIOC(N)MODEM: %m");
- if (ioctl(fd, (local || !modem)? TIOCNCAR: TIOCCAR) < 0)
- syslog(LOG_WARNING, "TIOC(N)CAR: %m");
-#endif
-
-#else /* SGTTY */
- int speed;
- struct sgttyb sgttyb;
+ p += 2; /* Skip address and control */
+ GETSHORT(protocol, p);
+ len -= PPP_HDRLEN;
/*
- * Put the tty in raw mode.
+ * Toss all non-LCP packets unless LCP is OPEN.
*/
- if (ioctl(fd, TIOCGETP, &sgttyb) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCGETP): %m");
- die(1);
+ if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
+ MAINDEBUG((LOG_INFO,
+ "get_input: Received non-LCP packet when LCP not open."));
+ return;
}
- if (!restore_term)
- initsgttyb = sgttyb;
-
- sgttyb.sg_flags = RAW | ANYP;
- speed = translate_speed(inspeed);
- if (speed)
- sgttyb.sg_ispeed = speed;
- else
- speed = sgttyb.sg_ispeed;
-
- if (ioctl(fd, TIOCSETP, &sgttyb) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETP): %m");
- die(1);
+ /*
+ * Until we get past the authentication phase, toss all packets
+ * except LCP, LQR and authentication packets.
+ */
+ if (phase <= PHASE_AUTHENTICATE
+ && !(protocol == PPP_LCP || protocol == PPP_LQR
+ || protocol == PPP_PAP || protocol == PPP_CHAP)) {
+ MAINDEBUG((LOG_INFO, "get_input: discarding proto 0x%x in phase %d",
+ protocol, phase));
+ return;
}
-#endif
- baud_rate = baud_rate_of(speed);
- restore_term = TRUE;
-}
-
-/*
- * setdtr - control the DTR line on the serial port.
- * This is called from die(), so it shouldn't call die().
- */
-setdtr(fd, on)
-int fd, on;
-{
- int modembits = TIOCM_DTR;
+ /*
+ * Upcall the proper protocol input routine.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+ if (protp->protocol == protocol && protp->enabled_flag) {
+ (*protp->input)(0, p, len);
+ return;
+ }
+ if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
+ && protp->datainput != NULL) {
+ (*protp->datainput)(0, p, len);
+ return;
+ }
+ }
- ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
+ if (debug)
+ syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
+ lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
}
/*
- * quit - Clean up state and exit.
+ * quit - Clean up state and exit (with an error indication).
*/
void
quit()
{
- die(0);
+ die(1);
}
/*
@@ -744,7 +715,7 @@ void
die(status)
int status;
{
- cleanup(0, NULL);
+ cleanup();
syslog(LOG_INFO, "Exit.");
exit(status);
}
@@ -753,47 +724,59 @@ die(status)
* cleanup - restore anything which needs to be restored before we exit
*/
/* ARGSUSED */
-void
-cleanup(status, arg)
- int status;
- caddr_t arg;
+static void
+cleanup()
{
- if (fd >= 0) {
- /* drop dtr to hang up */
- if (modem)
- setdtr(fd, FALSE);
+ sys_cleanup();
- if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
- syslog(LOG_WARNING, "fcntl(F_SETFL, fdflags): %m");
- initfdflags = -1;
+ if (ttyfd >= 0)
+ close_tty();
- disestablish_ppp();
+ if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT)
+ syslog(LOG_WARNING, "unable to delete pid file: %m");
+ pidfilename[0] = 0;
- if (restore_term) {
-#ifndef SGTTY
- if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
- syslog(LOG_WARNING, "tcsetattr: %m");
-#else
- if (ioctl(fd, TIOCSETP, &initsgttyb) < 0)
- syslog(LOG_WARNING, "ioctl(TIOCSETP): %m");
-#endif
- }
+ if (locked)
+ unlock();
+}
- close(fd);
- fd = -1;
+/*
+ * close_tty - restore the terminal device and close it.
+ */
+static void
+close_tty()
+{
+ disestablish_ppp(ttyfd);
+
+ /* drop dtr to hang up */
+ if (modem) {
+ setdtr(ttyfd, FALSE);
+ /*
+ * This sleep is in case the serial port has CLOCAL set by default,
+ * and consequently will reassert DTR when we close the device.
+ */
+ sleep(1);
}
- if (pidfilename[0] != 0 && unlink(pidfilename) < 0)
- syslog(LOG_WARNING, "unable to unlink pid file: %m");
- pidfilename[0] = 0;
+ restore_tty(ttyfd);
- if (lockflag && !default_device)
- unlock();
+ if (tty_mode != (mode_t) -1)
+ chmod(devnam, tty_mode);
+
+ close(ttyfd);
+ ttyfd = -1;
}
-static struct callout *callout = NULL; /* Callout list */
-static struct timeval schedtime; /* Time last timeout was set */
+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.
@@ -803,15 +786,14 @@ static struct timeval schedtime; /* Time last timeout was set */
*/
void
timeout(func, arg, time)
- void (*func)();
- caddr_t arg;
+ void (*func) __P((void *));
+ void *arg;
int time;
{
- struct itimerval itv;
- struct callout *newp, **oldpp;
+ struct callout *newp, *p, **pp;
- MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.",
- (int) func, (int) arg, time));
+ MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
+ (long) func, (long) arg, time));
/*
* Allocate timeout.
@@ -822,40 +804,20 @@ timeout(func, arg, time)
}
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 to link it in and decrement its time by the
- * amount of time used by preceding timeouts.
+ * Find correct place and link it in.
*/
- for (oldpp = &callout;
- *oldpp && (*oldpp)->c_time <= time;
- oldpp = &(*oldpp)->c_next)
- time -= (*oldpp)->c_time;
- newp->c_time = time;
- newp->c_next = *oldpp;
- if (*oldpp)
- (*oldpp)->c_time -= time;
- *oldpp = newp;
-
- /*
- * If this is now the first callout then we have to set a new
- * itimer.
- */
- if (callout == newp) {
- itv.it_interval.tv_sec = itv.it_interval.tv_usec =
- itv.it_value.tv_usec = 0;
- itv.it_value.tv_sec = callout->c_time;
- MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in timeout.",
- itv.it_value.tv_sec));
- if (setitimer(ITIMER_REAL, &itv, NULL)) {
- syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m");
- die(1);
- }
- if (gettimeofday(&schedtime, NULL)) {
- syslog(LOG_ERR, "gettimeofday: %m");
- die(1);
- }
- }
+ for (pp = &callout; (p = *pp); pp = &p->c_next)
+ if (newp->c_time.tv_sec < p->c_time.tv_sec
+ || (newp->c_time.tv_sec == p->c_time.tv_sec
+ && newp->c_time.tv_usec < p->c_time.tv_sec))
+ break;
+ newp->c_next = p;
+ *pp = newp;
}
@@ -864,194 +826,129 @@ timeout(func, arg, time)
*/
void
untimeout(func, arg)
- void (*func)();
- caddr_t arg;
+ void (*func) __P((void *));
+ void *arg;
{
- struct itimerval itv;
struct callout **copp, *freep;
- int reschedule = 0;
- MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg));
-
- /*
- * If the first callout is unscheduled then we have to set a new
- * itimer.
- */
- if (callout &&
- callout->c_func == func &&
- callout->c_arg == arg)
- reschedule = 1;
+ MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));
/*
- * Find first matching timeout. Add its time to the next timeouts
- * time.
+ * Find first matching timeout and remove it from the list.
*/
- for (copp = &callout; *copp; copp = &(*copp)->c_next)
- if ((*copp)->c_func == func &&
- (*copp)->c_arg == arg) {
- freep = *copp;
+ for (copp = &callout; (freep = *copp); copp = &freep->c_next)
+ if (freep->c_func == func && freep->c_arg == arg) {
*copp = freep->c_next;
- if (*copp)
- (*copp)->c_time += freep->c_time;
(void) free((char *) freep);
break;
}
-
- if (reschedule) {
- itv.it_interval.tv_sec = itv.it_interval.tv_usec =
- itv.it_value.tv_usec = 0;
- itv.it_value.tv_sec = callout ? callout->c_time : 0;
- MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in untimeout.",
- itv.it_value.tv_sec));
- if (setitimer(ITIMER_REAL, &itv, NULL)) {
- syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m");
- die(1);
- }
- if (gettimeofday(&schedtime, NULL)) {
- syslog(LOG_ERR, "gettimeofday: %m");
- die(1);
- }
- }
}
/*
- * adjtimeout - Decrement the first timeout by the amount of time since
- * it was scheduled.
+ * calltimeout - Call any timeout routines which are now due.
*/
-void
-adjtimeout()
+static void
+calltimeout()
{
- struct timeval tv;
- int timediff;
-
- if (callout == NULL)
- return;
- /*
- * Make sure that the clock hasn't been warped dramatically.
- * Account for recently expired, but blocked timer by adding
- * small fudge factor.
- */
- if (gettimeofday(&tv, NULL)) {
- syslog(LOG_ERR, "gettimeofday: %m");
- die(1);
+ struct callout *p;
+
+ while (callout != NULL) {
+ p = callout;
+
+ if (gettimeofday(&timenow, NULL) < 0) {
+ syslog(LOG_ERR, "Failed to get time of day: %m");
+ die(1);
+ }
+ if (!(p->c_time.tv_sec < timenow.tv_sec
+ || (p->c_time.tv_sec == timenow.tv_sec
+ && p->c_time.tv_usec <= timenow.tv_usec)))
+ break; /* no, it's not time yet */
+
+ callout = p->c_next;
+ (*p->c_func)(p->c_arg);
+
+ free((char *) p);
}
- timediff = tv.tv_sec - schedtime.tv_sec;
- if (timediff < 0 ||
- timediff > callout->c_time + 1)
- return;
-
- callout->c_time -= timediff; /* OK, Adjust time */
}
/*
- * hup - Catch SIGHUP signal.
- *
- * Indicates that the physical layer has been disconnected.
+ * timeleft - return the length of time until the next timeout is due.
*/
-static void
-hup(sig)
- int sig;
+static struct timeval *
+timeleft(tvp)
+ struct timeval *tvp;
{
- syslog(LOG_INFO, "Hangup (SIGHUP)");
+ 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;
- hungup = 1; /* they hung up on us! */
- persist = 0; /* don't try to restart */
- adjtimeout(); /* Adjust timeouts */
- lcp_lowerdown(0); /* Reset connection */
- quit(); /* and die */
+ return tvp;
}
/*
- * term - Catch SIGTERM signal.
- *
- * Indicates that we should initiate a graceful disconnect and exit.
+ * kill_my_pg - send a signal to our process group, and ignore it ourselves.
*/
static void
-term(sig)
+kill_my_pg(sig)
int sig;
{
- syslog(LOG_INFO, "Terminating link.");
- persist = 0; /* don't try to restart */
- adjtimeout(); /* Adjust timeouts */
- lcp_close(0); /* Close connection */
+ struct sigaction act, oldact;
+
+ act.sa_handler = SIG_IGN;
+ act.sa_flags = 0;
+ kill(0, sig);
+ sigaction(sig, &act, &oldact);
+ sigaction(sig, &oldact, NULL);
}
/*
- * intr - Catch SIGINT signal (DEL/^C).
+ * hup - Catch SIGHUP signal.
*
- * Indicates that we should initiate a graceful disconnect and exit.
+ * Indicates that the physical layer has been disconnected.
+ * We don't rely on this indication; if the user has sent this
+ * signal, we just take the link down.
*/
static void
-intr(sig)
+hup(sig)
int sig;
{
- syslog(LOG_INFO, "Interrupt received: terminating link");
- persist = 0; /* don't try to restart */
- adjtimeout(); /* Adjust timeouts */
- lcp_close(0); /* Close connection */
+ syslog(LOG_INFO, "Hangup (SIGHUP)");
+ kill_link = 1;
+ if (conn_running)
+ /* Send the signal to the [dis]connector process(es) also */
+ kill_my_pg(sig);
}
/*
- * alrm - Catch SIGALRM signal.
+ * term - Catch SIGTERM signal and SIGINT signal (^C/del).
*
- * Indicates a timeout.
+ * Indicates that we should initiate a graceful disconnect and exit.
*/
+/*ARGSUSED*/
static void
-alrm(sig)
+term(sig)
int sig;
{
- struct itimerval itv;
- struct callout *freep, *list, *last;
-
- MAINDEBUG((LOG_DEBUG, "Alarm"));
-
- if (callout == NULL)
- return;
- /*
- * Get the first scheduled timeout and any that were scheduled
- * for the same time as a list, and remove them all from callout
- * list.
- */
- list = last = callout;
- while (last->c_next != NULL && last->c_next->c_time == 0)
- last = last->c_next;
- callout = last->c_next;
- last->c_next = NULL;
-
- /*
- * Set a new itimer if there are more timeouts scheduled.
- */
- if (callout) {
- itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0;
- itv.it_value.tv_usec = 0;
- itv.it_value.tv_sec = callout->c_time;
- MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in alrm.",
- itv.it_value.tv_sec));
- if (setitimer(ITIMER_REAL, &itv, NULL)) {
- syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m");
- die(1);
- }
- if (gettimeofday(&schedtime, NULL)) {
- syslog(LOG_ERR, "gettimeofday: %m");
- die(1);
- }
- }
-
- /*
- * Now call all the timeout routines scheduled for this time.
- */
- while (list) {
- (*list->c_func)(list->c_arg);
- freep = list;
- list = list->c_next;
- (void) free((char *) freep);
- }
-
+ syslog(LOG_INFO, "Terminating on signal %d.", sig);
+ persist = 0; /* don't try to restart */
+ kill_link = 1;
+ if (conn_running)
+ /* Send the signal to the [dis]connector process(es) also */
+ kill_my_pg(sig);
}
@@ -1068,129 +965,49 @@ chld(sig)
/*
- * io - Catch SIGIO signal.
+ * toggle_debug - Catch SIGUSR1 signal.
*
- * Indicates that incoming data is available.
+ * Toggle debug flag.
*/
+/*ARGSUSED*/
static void
-io(sig)
+toggle_debug(sig)
int sig;
{
- int len, i;
- u_char *p;
- u_short protocol;
- fd_set fdset;
- struct timeval notime;
- int ready;
-
- MAINDEBUG((LOG_DEBUG, "IO signal received"));
- adjtimeout(); /* Adjust timeouts */
-
- /* Yup, this is for real */
- for (;;) { /* Read all available packets */
- p = inpacket_buf; /* point to beginning of packet buffer */
-
- len = read_packet(inpacket_buf);
- if (len < 0)
- return;
-
- if (len == 0) {
- MAINDEBUG((LOG_DEBUG, "End of file on fd!"));
- lcp_lowerdown(0);
- return;
- }
-
- if (debug /*&& (debugflags & DBG_INPACKET)*/)
- log_packet(p, len, "rcvd ");
-
- if (len < DLLHEADERLEN) {
- MAINDEBUG((LOG_INFO, "io(): Received short packet."));
- return;
- }
-
- p += 2; /* Skip address and control */
- GETSHORT(protocol, p);
- len -= DLLHEADERLEN;
-
- /*
- * Toss all non-LCP packets unless LCP is OPEN.
- */
- if (protocol != LCP && lcp_fsm[0].state != OPENED) {
- MAINDEBUG((LOG_INFO,
- "io(): Received non-LCP packet when LCP not open."));
- return;
- }
-
- /*
- * Upcall the proper protocol input routine.
- */
- for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
- if (prottbl[i].protocol == protocol) {
- (*prottbl[i].input)(0, p, len);
- break;
- }
-
- if (i == sizeof (prottbl) / sizeof (struct protent)) {
- syslog(LOG_WARNING, "input: Unknown protocol (%x) received!",
- protocol);
- lcp_sprotrej(0, p - DLLHEADERLEN, len + DLLHEADERLEN);
- }
+ debug = !debug;
+ if (debug) {
+ setlogmask(LOG_UPTO(LOG_DEBUG));
+ } else {
+ setlogmask(LOG_UPTO(LOG_WARNING));
}
}
-/*
- * demuxprotrej - Demultiplex a Protocol-Reject.
- */
-void
-demuxprotrej(unit, protocol)
- int unit;
- u_short protocol;
-{
- int i;
-
- /*
- * Upcall the proper Protocol-Reject routine.
- */
- for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
- if (prottbl[i].protocol == protocol) {
- (*prottbl[i].protrej)(unit);
- return;
- }
-
- syslog(LOG_WARNING,
- "demuxprotrej: Unrecognized Protocol-Reject for protocol %d!",
- protocol);
-}
-
/*
- * incdebug - Catch SIGUSR1 signal.
+ * open_ccp - Catch SIGUSR2 signal.
*
- * Increment debug flag.
+ * Try to (re)negotiate compression.
*/
/*ARGSUSED*/
static void
-incdebug(sig)
+open_ccp(sig)
int sig;
{
- syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
- setlogmask(LOG_UPTO(LOG_DEBUG));
- debug++;
+ open_ccp_flag = 1;
}
/*
- * nodebug - Catch SIGUSR2 signal.
- *
- * Turn off debugging.
+ * bad_signal - We've caught a fatal signal. Clean up state and exit.
*/
-/*ARGSUSED*/
static void
-nodebug(sig)
+bad_signal(sig)
int sig;
{
- setlogmask(LOG_UPTO(LOG_WARNING));
- debug = 0;
+ syslog(LOG_ERR, "Fatal signal %d", sig);
+ if (conn_running)
+ kill_my_pg(SIGTERM);
+ die(1);
}
@@ -1198,33 +1015,55 @@ nodebug(sig)
* device_script - run a program to connect or disconnect the
* serial device.
*/
-int
+static int
device_script(program, in, out)
char *program;
int in, out;
{
int pid;
int status;
- sigset_t mask;
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGHUP);
- sigprocmask(SIG_BLOCK, &mask, &mask);
+ int errfd;
+ conn_running = 1;
pid = fork();
if (pid < 0) {
- syslog(LOG_ERR, "fork: %m");
+ conn_running = 0;
+ syslog(LOG_ERR, "Failed to create child process: %m");
die(1);
}
if (pid == 0) {
- setreuid(getuid(), getuid());
- setregid(getgid(), getgid());
- sigprocmask(SIG_SETMASK, &mask, NULL);
- dup2(in, 0);
- dup2(out, 1);
+ sys_close();
+ closelog();
+ if (in == out) {
+ if (in != 0) {
+ dup2(in, 0);
+ close(in);
+ }
+ dup2(0, 1);
+ } else {
+ if (out == 0)
+ out = dup(out);
+ if (in != 0) {
+ dup2(in, 0);
+ close(in);
+ }
+ if (out != 1) {
+ dup2(out, 1);
+ close(out);
+ }
+ }
+ if (redirect_stderr) {
+ close(2);
+ errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644);
+ if (errfd >= 0 && errfd != 2) {
+ dup2(errfd, 2);
+ close(errfd);
+ }
+ }
+ setuid(getuid());
+ setgid(getgid());
execl("/bin/sh", "sh", "-c", program, (char *)0);
syslog(LOG_ERR, "could not exec /bin/sh: %m");
_exit(99);
@@ -1234,10 +1073,10 @@ device_script(program, in, out)
while (waitpid(pid, &status, 0) < 0) {
if (errno == EINTR)
continue;
- syslog(LOG_ERR, "waiting for (dis)connection process: %m");
+ syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
die(1);
}
- sigprocmask(SIG_SETMASK, &mask, NULL);
+ conn_running = 0;
return (status == 0 ? 0 : -1);
}
@@ -1256,16 +1095,55 @@ run_program(prog, args, must_exist)
int must_exist;
{
int pid;
+ char *nullenv[1];
pid = fork();
if (pid == -1) {
- syslog(LOG_ERR, "can't fork to run %s: %m", prog);
+ syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
return -1;
}
if (pid == 0) {
- execv(prog, args);
+ int new_fd;
+
+ /* Leave the current location */
+ (void) setsid(); /* No controlling tty. */
+ (void) umask (S_IRWXG|S_IRWXO);
+ (void) chdir ("/"); /* no current directory. */
+ setuid(geteuid());
+ setgid(getegid());
+
+ /* Ensure that nothing of our device environment is inherited. */
+ sys_close();
+ closelog();
+ close (0);
+ close (1);
+ close (2);
+ close (ttyfd); /* tty interface to the ppp device */
+
+ /* Don't pass handles to the PPP device, even by accident. */
+ new_fd = open (_PATH_DEVNULL, O_RDWR);
+ if (new_fd >= 0) {
+ if (new_fd != 0) {
+ dup2 (new_fd, 0); /* stdin <- /dev/null */
+ close (new_fd);
+ }
+ dup2 (0, 1); /* stdout -> /dev/null */
+ dup2 (0, 2); /* stderr -> /dev/null */
+ }
+
+#ifdef BSD
+ /* Force the priority back to zero if pppd is running higher. */
+ if (setpriority (PRIO_PROCESS, 0, 0) < 0)
+ syslog (LOG_WARNING, "can't reset priority to 0: %m");
+#endif
+
+ /* SysV recommends a second fork at this point. */
+
+ /* run the program; give it a null environment */
+ nullenv[0] = NULL;
+ execve(prog, args, nullenv);
if (must_exist || errno != ENOENT)
- syslog(LOG_WARNING, "can't execute %s: %m", prog);
+ syslog(LOG_WARNING, "Can't execute %s: %m", prog);
_exit(-1);
}
MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
@@ -1278,7 +1156,7 @@ run_program(prog, args, must_exist)
* reap_kids - get status from any dead child processes,
* and log a message for abnormal terminations.
*/
-void
+static void
reap_kids()
{
int pid, status;
@@ -1287,13 +1165,13 @@ reap_kids()
return;
if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
if (errno != ECHILD)
- syslog(LOG_ERR, "waitpid: %m");
+ syslog(LOG_ERR, "Error waiting for child process: %m");
return;
}
if (pid > 0) {
--n_children;
if (WIFSIGNALED(status)) {
- syslog(LOG_WARNING, "child process %d terminated with signal %d",
+ syslog(LOG_WARNING, "Child process %d terminated with signal %d",
pid, WTERMSIG(status));
}
}
@@ -1308,16 +1186,17 @@ char line[256]; /* line to be logged accumulated here */
char *linep;
void
-log_packet(p, len, prefix)
+log_packet(p, len, prefix, level)
u_char *p;
int len;
char *prefix;
+ int level;
{
strcpy(line, prefix);
linep = line + strlen(line);
format_packet(p, len, pr_log, NULL);
if (linep != line)
- syslog(LOG_DEBUG, "%s", line);
+ syslog(level, "%s", line);
}
/*
@@ -1328,23 +1207,24 @@ void
format_packet(p, len, printer, arg)
u_char *p;
int len;
- void (*printer) __ARGS((void *, char *, ...));
+ void (*printer) __P((void *, char *, ...));
void *arg;
{
int i, n;
u_short proto;
u_char x;
+ struct protent *protp;
- if (len >= DLLHEADERLEN && p[0] == ALLSTATIONS && p[1] == UI) {
+ if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
p += 2;
GETSHORT(proto, p);
- len -= DLLHEADERLEN;
- for (i = 0; i < N_PROTO; ++i)
- if (proto == prottbl[i].protocol)
+ len -= PPP_HDRLEN;
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (proto == protp->protocol)
break;
- if (i < N_PROTO) {
- printer(arg, "[%s", prottbl[i].name);
- n = (*prottbl[i].printpkt)(p, len, printer, arg);
+ if (protp != NULL) {
+ printer(arg, "[%s", protp->name);
+ n = (*protp->printpkt)(p, len, printer, arg);
printer(arg, "]");
p += n;
len -= n;
@@ -1359,43 +1239,23 @@ format_packet(p, len, printer, arg)
}
}
-#ifdef __STDC__
-#include <stdarg.h>
-
-void
-pr_log(void *arg, char *fmt, ...)
+static void
+pr_log __V((void *arg, char *fmt, ...))
{
int n;
va_list pvar;
char buf[256];
+#if __STDC__
va_start(pvar, fmt);
- vsprintf(buf, fmt, pvar);
- va_end(pvar);
-
- n = strlen(buf);
- if (linep + n + 1 > line + sizeof(line)) {
- syslog(LOG_DEBUG, "%s", line);
- linep = line;
- }
- strcpy(linep, buf);
- linep += n;
-}
-
-#else /* __STDC__ */
-#include <varargs.h>
-
-void
-pr_log(arg, fmt, va_alist)
-void *arg;
-char *fmt;
-va_dcl
-{
- int n;
- va_list pvar;
- char buf[256];
-
+#else
+ void *arg;
+ char *fmt;
va_start(pvar);
+ arg = va_arg(pvar, void *);
+ fmt = va_arg(pvar, char *);
+#endif
+
vsprintf(buf, fmt, pvar);
va_end(pvar);
@@ -1407,7 +1267,6 @@ va_dcl
strcpy(linep, buf);
linep += n;
}
-#endif
/*
* print_string - print a readable representation of a string using
@@ -1417,7 +1276,7 @@ void
print_string(p, len, printer, arg)
char *p;
int len;
- void (*printer) __ARGS((void *, char *, ...));
+ void (*printer) __P((void *, char *, ...));
void *arg;
{
int c;
@@ -1425,10 +1284,25 @@ print_string(p, len, printer, arg)
printer(arg, "\"");
for (; len > 0; --len) {
c = *p++;
- if (' ' <= c && c <= '~')
+ if (' ' <= c && c <= '~') {
+ if (c == '\\' || c == '"')
+ printer(arg, "\\");
printer(arg, "%c", c);
- else
- printer(arg, "\\%.3o", 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, "\"");
}
@@ -1443,3 +1317,252 @@ novm(msg)
syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
die(1);
}
+
+/*
+ * fmtmsg - format a message into a buffer. Like sprintf except we
+ * also specify the length of the output buffer, and we handle
+ * %r (recursive format), %m (error message) and %I (IP address) formats.
+ * Doesn't do floating-point formats.
+ * Returns the number of chars put into buf.
+ */
+int
+fmtmsg __V((char *buf, int buflen, char *fmt, ...))
+{
+ va_list args;
+ int n;
+
+#if __STDC__
+ va_start(args, fmt);
+#else
+ char *buf;
+ int buflen;
+ char *fmt;
+ va_start(args);
+ buf = va_arg(args, char *);
+ buflen = va_arg(args, int);
+ fmt = va_arg(args, char *);
+#endif
+ n = vfmtmsg(buf, buflen, fmt, args);
+ va_end(args);
+ return n;
+}
+
+/*
+ * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
+ */
+#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
+
+int
+vfmtmsg(buf, buflen, fmt, args)
+ char *buf;
+ int buflen;
+ char *fmt;
+ va_list args;
+{
+ int c, i, n;
+ int width, prec, fillch;
+ int base, len, neg, quoted;
+ unsigned long val = 0;
+ char *str, *f, *buf0;
+ unsigned char *p;
+ char num[32];
+ time_t t;
+ static char hexchars[] = "0123456789abcdef";
+
+ buf0 = buf;
+ --buflen;
+ while (buflen > 0) {
+ for (f = fmt; *f != '%' && *f != 0; ++f)
+ ;
+ if (f > fmt) {
+ len = f - fmt;
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, fmt, len);
+ buf += len;
+ buflen -= len;
+ fmt = f;
+ }
+ if (*fmt == 0)
+ break;
+ c = *++fmt;
+ width = prec = 0;
+ fillch = ' ';
+ if (c == '0') {
+ fillch = '0';
+ c = *++fmt;
+ }
+ if (c == '*') {
+ width = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ while (isdigit(c)) {
+ width = width * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ if (c == '.') {
+ c = *++fmt;
+ if (c == '*') {
+ prec = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ while (isdigit(c)) {
+ prec = prec * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ }
+ str = 0;
+ base = 0;
+ neg = 0;
+ ++fmt;
+ switch (c) {
+ case 'd':
+ i = va_arg(args, int);
+ if (i < 0) {
+ neg = 1;
+ val = -i;
+ } else
+ val = i;
+ base = 10;
+ break;
+ case 'o':
+ val = va_arg(args, unsigned int);
+ base = 8;
+ break;
+ case 'x':
+ val = va_arg(args, unsigned int);
+ base = 16;
+ break;
+ case 'p':
+ val = (unsigned long) va_arg(args, void *);
+ base = 16;
+ neg = 2;
+ break;
+ case 's':
+ str = va_arg(args, char *);
+ break;
+ case 'c':
+ num[0] = va_arg(args, int);
+ num[1] = 0;
+ str = num;
+ break;
+ case 'm':
+ str = strerror(errno);
+ break;
+ case 'I':
+ str = ip_ntoa(va_arg(args, u_int32_t));
+ break;
+ case 'r':
+ f = va_arg(args, char *);
+#ifndef __powerpc__
+ n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list));
+#else
+ /* On the powerpc, a va_list is an array of 1 structure */
+ n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *));
+#endif
+ buf += n;
+ buflen -= n;
+ continue;
+ case 't':
+ time(&t);
+ str = ctime(&t);
+ str += 4; /* chop off the day name */
+ str[15] = 0; /* chop off year and newline */
+ break;
+ case 'v': /* "visible" string */
+ case 'q': /* quoted string */
+ quoted = c == 'q';
+ p = va_arg(args, unsigned char *);
+ if (fillch == '0' && prec > 0) {
+ n = prec;
+ } else {
+ n = strlen((char *)p);
+ if (prec > 0 && prec < n)
+ n = prec;
+ }
+ while (n > 0 && buflen > 0) {
+ c = *p++;
+ --n;
+ if (!quoted && c >= 0x80) {
+ OUTCHAR('M');
+ OUTCHAR('-');
+ c -= 0x80;
+ }
+ if (quoted && (c == '"' || c == '\\'))
+ OUTCHAR('\\');
+ if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
+ if (quoted) {
+ OUTCHAR('\\');
+ switch (c) {
+ case '\t': OUTCHAR('t'); break;
+ case '\n': OUTCHAR('n'); break;
+ case '\b': OUTCHAR('b'); break;
+ case '\f': OUTCHAR('f'); break;
+ default:
+ OUTCHAR('x');
+ OUTCHAR(hexchars[c >> 4]);
+ OUTCHAR(hexchars[c & 0xf]);
+ }
+ } else {
+ if (c == '\t')
+ OUTCHAR(c);
+ else {
+ OUTCHAR('^');
+ OUTCHAR(c ^ 0x40);
+ }
+ }
+ } else
+ OUTCHAR(c);
+ }
+ continue;
+ default:
+ *buf++ = '%';
+ if (c != '%')
+ --fmt; /* so %z outputs %z etc. */
+ --buflen;
+ continue;
+ }
+ if (base != 0) {
+ str = num + sizeof(num);
+ *--str = 0;
+ while (str > num + neg) {
+ *--str = hexchars[val % base];
+ val = val / base;
+ if (--prec <= 0 && val == 0)
+ break;
+ }
+ switch (neg) {
+ case 1:
+ *--str = '-';
+ break;
+ case 2:
+ *--str = 'x';
+ *--str = '0';
+ break;
+ }
+ len = num + sizeof(num) - 1 - str;
+ } else {
+ len = strlen(str);
+ if (prec > 0 && len > prec)
+ len = prec;
+ }
+ if (width > 0) {
+ if (width > buflen)
+ width = buflen;
+ if ((n = width - len) > 0) {
+ buflen -= n;
+ for (; n > 0; --n)
+ *buf++ = fillch;
+ }
+ }
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, str, len);
+ buf += len;
+ buflen -= len;
+ }
+ *buf = 0;
+ return buf - buf0;
+}
diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c
index ef1fc8a..d8c3983 100644
--- a/usr.sbin/pppd/options.c
+++ b/usr.sbin/pppd/options.c
@@ -18,9 +18,10 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: options.c,v 1.10 1994/05/27 00:43:34 paulus Exp $";
+static char rcsid[] = "$Id: options.c,v 1.40 1997/11/27 06:09:34 paulus Exp $";
#endif
+#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
@@ -34,8 +35,12 @@ static char rcsid[] = "$Id: options.c,v 1.10 1994/05/27 00:43:34 paulus Exp $";
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef PPP_FILTER
+#include <pcap.h>
+#include <pcap-int.h> /* XXX: To get struct pcap */
+#endif
-#include "ppp.h"
#include "pppd.h"
#include "pathnames.h"
#include "patchlevel.h"
@@ -44,116 +49,213 @@ static char rcsid[] = "$Id: options.c,v 1.10 1994/05/27 00:43:34 paulus Exp $";
#include "ipcp.h"
#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
-#ifdef ultrix
-char *strdup __ARGS((char *));
+#if defined(ultrix) || defined(NeXT)
+char *strdup __P((char *));
#endif
#ifndef GIDSET_TYPE
-#define GIDSET_TYPE int
+#define GIDSET_TYPE gid_t
#endif
/*
- * Prototypes
+ * Option variables and default values.
*/
-static int setdebug __ARGS((void));
-static int setkdebug __ARGS((char **));
-static int setpassive __ARGS((void));
-static int setsilent __ARGS((void));
-static int noopt __ARGS((void));
-static int setnovj __ARGS((void));
-static int setnovjccomp __ARGS((void));
-static int setvjslots __ARGS((char **));
-static int reqpap __ARGS((void));
-static int nopap __ARGS((void));
-static int setupapfile __ARGS((char **));
-static int nochap __ARGS((void));
-static int reqchap __ARGS((void));
-static int setspeed __ARGS((char *));
-static int noaccomp __ARGS((void));
-static int noasyncmap __ARGS((void));
-static int noipaddr __ARGS((void));
-static int nomagicnumber __ARGS((void));
-static int setasyncmap __ARGS((char **));
-static int setescape __ARGS((char **));
-static int setmru __ARGS((char **));
-static int setmtu __ARGS((char **));
-static int nomru __ARGS((void));
-static int nopcomp __ARGS((void));
-static int setconnector __ARGS((char **));
-static int setdisconnector __ARGS((char **));
-static int setdomain __ARGS((char **));
-static int setnetmask __ARGS((char **));
-static int setcrtscts __ARGS((void));
-static int setxonxoff __ARGS((void));
-static int setnodetach __ARGS((void));
-static int setmodem __ARGS((void));
-static int setlocal __ARGS((void));
-static int setlock __ARGS((void));
-static int setname __ARGS((char **));
-static int setuser __ARGS((char **));
-static int setremote __ARGS((char **));
-static int setauth __ARGS((void));
-static int readfile __ARGS((char **));
-static int setdefaultroute __ARGS((void));
-static int setproxyarp __ARGS((void));
-static int setpersist __ARGS((void));
-static int setdologin __ARGS((void));
-static int setusehostname __ARGS((void));
-static int setnoipdflt __ARGS((void));
-static int setlcptimeout __ARGS((char **));
-static int setlcpterm __ARGS((char **));
-static int setlcpconf __ARGS((char **));
-static int setlcpfails __ARGS((char **));
-static int setipcptimeout __ARGS((char **));
-static int setipcpterm __ARGS((char **));
-static int setipcpconf __ARGS((char **));
-static int setipcpfails __ARGS((char **));
-static int setpaptimeout __ARGS((char **));
-static int setpapreqs __ARGS((char **));
-static int setchaptimeout __ARGS((char **));
-static int setchapchal __ARGS((char **));
-static int setchapintv __ARGS((char **));
-static int setipcpaccl __ARGS((void));
-static int setipcpaccr __ARGS((void));
-static int setlcpechointv __ARGS((char **));
-static int setlcpechofails __ARGS((char **));
-
-static int number_option __ARGS((char *, long *, int));
-static int readable __ARGS((int fd));
+#ifdef PPP_FILTER
+int dflag = 0; /* Tell libpcap we want debugging */
+#endif
+int debug = 0; /* Debug flag */
+int kdebugflag = 0; /* Tell kernel to print debug messages */
+int default_device = 1; /* Using /dev/tty or equivalent */
+char devnam[MAXPATHLEN] = "/dev/tty"; /* Device name */
+int crtscts = 0; /* Use hardware flow control */
+int modem = 1; /* Use modem control lines */
+int inspeed = 0; /* Input/Output speed requested */
+u_int32_t netmask = 0; /* IP netmask to set on interface */
+int lockflag = 0; /* Create lock file to lock the serial dev */
+int nodetach = 0; /* Don't detach from controlling tty */
+char *connector = NULL; /* Script to establish physical link */
+char *disconnector = NULL; /* Script to disestablish physical link */
+char *welcomer = NULL; /* Script to run after phys link estab. */
+int maxconnect = 0; /* Maximum connect time */
+char user[MAXNAMELEN]; /* Username for PAP */
+char passwd[MAXSECRETLEN]; /* Password for PAP */
+int auth_required = 0; /* Peer is required to authenticate */
+int defaultroute = 0; /* assign default route through interface */
+int proxyarp = 0; /* Set up proxy ARP entry for peer */
+int persist = 0; /* Reopen link after it goes down */
+int uselogin = 0; /* Use /etc/passwd for checking PAP */
+int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
+int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
+char our_name[MAXNAMELEN]; /* Our name for authentication purposes */
+char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+int explicit_remote = 0; /* User specified explicit remote name */
+int usehostname = 0; /* Use hostname for our_name */
+int disable_defaultip = 0; /* Don't use hostname for default IP adrs */
+int demand = 0; /* do dial-on-demand */
+char *ipparam = NULL; /* Extra parameter for ip up/down scripts */
+int cryptpap; /* Passwords in pap-secrets are encrypted */
+int idle_time_limit = 0; /* Disconnect if idle for this many seconds */
+int holdoff = 30; /* # seconds to pause before reconnecting */
+int refuse_pap = 0; /* Set to say we won't do PAP */
+int refuse_chap = 0; /* Set to say we won't do CHAP */
+
+#ifdef MSLANMAN
+int ms_lanman = 0; /* Nonzero if use LanMan password instead of NT */
+ /* Has meaning only with MS-CHAP challenges */
+#endif
+
+struct option_info auth_req_info;
+struct option_info connector_info;
+struct option_info disconnector_info;
+struct option_info welcomer_info;
+struct option_info devnam_info;
+#ifdef PPP_FILTER
+struct bpf_program pass_filter;/* Filter program for packets to pass */
+struct bpf_program active_filter; /* Filter program for link-active pkts */
+pcap_t pc; /* Fake struct pcap so we can compile expr */
+#endif
/*
- * Option variables
+ * Prototypes
*/
-extern char *progname;
-extern int debug;
-extern int kdebugflag;
-extern int modem;
-extern int lockflag;
-extern int crtscts;
-extern int nodetach;
-extern char *connector;
-extern char *disconnector;
-extern int inspeed;
-extern char devname[];
-extern int default_device;
-extern u_long netmask;
-extern int detach;
-extern char user[];
-extern char passwd[];
-extern int auth_required;
-extern int proxyarp;
-extern int persist;
-extern int uselogin;
-extern u_long lcp_echo_interval;
-extern u_long lcp_echo_fails;
-extern char our_name[];
-extern char remote_name[];
-int usehostname;
-int disable_defaultip;
+static int setdevname __P((char *, int));
+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 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 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 **));
+
+#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 int number_option __P((char *, u_int32_t *, int));
+static int int_option __P((char *, int *));
+static int readable __P((int fd));
/*
* Valid arguments.
@@ -161,39 +263,60 @@ int disable_defaultip;
static struct cmd {
char *cmd_name;
int num_args;
- int (*cmd_func)();
+ int (*cmd_func) __P((char **));
} cmds[] = {
- {"-all", 0, noopt}, /* Don't request/allow any options */
+ {"-all", 0, noopt}, /* Don't request/allow any options (useless) */
+ {"noaccomp", 0, noaccomp}, /* Disable Address/Control compression */
{"-ac", 0, noaccomp}, /* Disable Address/Control compress */
+ {"default-asyncmap", 0, noasyncmap}, /* Disable asyncmap negoatiation */
{"-am", 0, noasyncmap}, /* Disable asyncmap negotiation */
{"-as", 1, setasyncmap}, /* set the desired async map */
{"-d", 0, setdebug}, /* Increase debugging level */
+ {"nodetach", 0, setnodetach}, /* Don't detach from controlling tty */
{"-detach", 0, setnodetach}, /* don't fork */
- {"-ip", 0, noipaddr}, /* Disable IP address negotiation */
+ {"noip", 0, noip}, /* Disable IP and IPCP */
+ {"-ip", 0, noip}, /* Disable IP and IPCP */
+ {"nomagic", 0, nomagicnumber}, /* Disable magic number negotiation */
{"-mn", 0, nomagicnumber}, /* Disable magic number negotiation */
+ {"default-mru", 0, nomru}, /* Disable MRU negotiation */
{"-mru", 0, nomru}, /* Disable mru negotiation */
{"-p", 0, setpassive}, /* Set passive mode */
+ {"nopcomp", 0, nopcomp}, /* Disable protocol field compression */
{"-pc", 0, nopcomp}, /* Disable protocol field compress */
+#if OLD_OPTIONS
{"+ua", 1, setupapfile}, /* Get PAP user and password from file */
+#endif
+ {"require-pap", 0, reqpap}, /* Require PAP authentication from peer */
{"+pap", 0, reqpap}, /* Require PAP auth from peer */
+ {"refuse-pap", 0, nopap}, /* Don't agree to auth to peer with PAP */
{"-pap", 0, nopap}, /* Don't allow UPAP authentication with peer */
+ {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */
{"+chap", 0, reqchap}, /* Require CHAP authentication from peer */
+ {"refuse-chap", 0, nochap}, /* Don't agree to auth to peer with CHAP */
{"-chap", 0, nochap}, /* Don't allow CHAP authentication with peer */
+ {"novj", 0, setnovj}, /* Disable VJ compression */
{"-vj", 0, setnovj}, /* disable VJ compression */
+ {"novjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
{"-vjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
{"vj-max-slots", 1, setvjslots}, /* Set maximum VJ header slots */
{"asyncmap", 1, setasyncmap}, /* set the desired async map */
{"escape", 1, setescape}, /* set chars to escape on transmission */
{"connect", 1, setconnector}, /* A program to set up a connection */
{"disconnect", 1, setdisconnector}, /* program to disconnect serial dev. */
+ {"welcome", 1, setwelcomer},/* Script to welcome client */
+ {"maxconnect", 1, setmaxconnect}, /* specify a maximum connect time */
{"crtscts", 0, setcrtscts}, /* set h/w flow control */
+ {"nocrtscts", 0, setnocrtscts}, /* clear h/w flow control */
+ {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */
{"xonxoff", 0, setxonxoff}, /* set s/w flow control */
- {"-crtscts", 0, setxonxoff}, /* another name for xonxoff */
{"debug", 0, setdebug}, /* Increase debugging level */
{"kdebug", 1, setkdebug}, /* Enable kernel-level debugging */
{"domain", 1, setdomain}, /* Add given domain name to hostname*/
{"mru", 1, setmru}, /* Set MRU value for negotiation */
{"mtu", 1, setmtu}, /* Set our MTU */
+#ifdef CBCP_SUPPORT
+ {"callback", 1, setcbcp}, /* Ask for callback */
+#endif
{"netmask", 1, setnetmask}, /* set netmask */
{"passive", 0, setpassive}, /* Set passive mode */
{"silent", 0, setsilent}, /* Set silent mode */
@@ -201,14 +324,22 @@ static struct cmd {
{"local", 0, setlocal}, /* Don't use modem control lines */
{"lock", 0, setlock}, /* Lock serial device (with lock file) */
{"name", 1, setname}, /* Set local name for authentication */
- {"user", 1, setuser}, /* Set username for PAP auth with peer */
+ {"user", 1, setuser}, /* Set name for auth with peer */
{"usehostname", 0, setusehostname}, /* Must use hostname for auth. */
{"remotename", 1, setremote}, /* Set remote name for authentication */
{"auth", 0, setauth}, /* Require authentication from peer */
+ {"noauth", 0, setnoauth}, /* Don't require peer to authenticate */
{"file", 1, readfile}, /* Take options from a file */
+ {"call", 1, callfile}, /* Take options from a privileged file */
{"defaultroute", 0, setdefaultroute}, /* Add default route */
+ {"nodefaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
+ {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
{"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */
+ {"noproxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
+ {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
{"persist", 0, setpersist}, /* Keep on reopening connection after close */
+ {"nopersist", 0, setnopersist}, /* Turn off persist option */
+ {"demand", 0, setdemand}, /* Dial on demand */
{"login", 0, setdologin}, /* Use system password database for UPAP */
{"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */
{"lcp-echo-failure", 1, setlcpechofails}, /* consecutive echo failures */
@@ -221,13 +352,66 @@ static struct cmd {
{"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */
{"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */
{"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */
- {"pap-restart", 1, setpaptimeout}, /* Set timeout for UPAP */
+ {"pap-restart", 1, setpaptimeout}, /* Set retransmit timeout for PAP */
{"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */
+ {"pap-timeout", 1, setpapreqtime}, /* Set time limit for peer PAP auth. */
{"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */
{"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */
{"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */
{"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */
{"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */
+ {"noccp", 0, noccp}, /* Disable CCP negotiation */
+ {"-ccp", 0, noccp}, /* Disable CCP negotiation */
+ {"bsdcomp", 1, setbsdcomp}, /* request BSD-Compress */
+ {"nobsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */
+ {"-bsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */
+ {"deflate", 1, setdeflate}, /* request Deflate compression */
+ {"nodeflate", 0, setnodeflate}, /* don't allow Deflate compression */
+ {"-deflate", 0, setnodeflate}, /* don't allow Deflate compression */
+ {"predictor1", 0, setpred1comp}, /* request Predictor-1 */
+ {"nopredictor1", 0, setnopred1comp},/* don't allow Predictor-1 */
+ {"-predictor1", 0, setnopred1comp}, /* don't allow Predictor-1 */
+ {"ipparam", 1, setipparam}, /* set ip script parameter */
+ {"papcrypt", 0, setpapcrypt}, /* PAP passwords encrypted */
+ {"idle", 1, setidle}, /* idle time limit (seconds) */
+ {"holdoff", 1, setholdoff}, /* set holdoff time (seconds) */
+ {"ms-dns", 1, setdnsaddr}, /* DNS address for the peer's use */
+ {"ms-wins", 1, setwinsaddr}, /* Nameserver for SMB over TCP/IP for peer */
+ {"noipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */
+ {"-ipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */
+ {"--version", 0, showversion}, /* Show version number */
+ {"--help", 0, showhelp}, /* Show brief listing of options */
+ {"-h", 0, showhelp}, /* ditto */
+
+#ifdef PPP_FILTER
+ {"pdebug", 1, setpdebug}, /* libpcap debugging */
+ {"pass-filter", 1, setpassfilter}, /* set filter for packets to pass */
+ {"active-filter", 1, setactivefilter}, /* set filter for active pkts */
+#endif
+
+#ifdef IPX_CHANGE
+ {"ipx-network", 1, setipxnetwork}, /* IPX network number */
+ {"ipxcp-accept-network", 0, setipxanet}, /* Accept peer netowrk */
+ {"ipx-node", 1, setipxnode}, /* IPX node number */
+ {"ipxcp-accept-local", 0, setipxalcl}, /* Accept our address */
+ {"ipxcp-accept-remote", 0, setipxarmt}, /* Accept peer's address */
+ {"ipx-routing", 1, setipxrouter}, /* IPX routing proto number */
+ {"ipx-router-name", 1, setipxname}, /* IPX router name */
+ {"ipxcp-restart", 1, setipxcptimeout}, /* Set timeout for IPXCP */
+ {"ipxcp-max-terminate", 1, setipxcpterm}, /* max #xmits for term-reqs */
+ {"ipxcp-max-configure", 1, setipxcpconf}, /* max #xmits for conf-reqs */
+ {"ipxcp-max-failure", 1, setipxcpfails}, /* max #conf-naks for IPXCP */
+#if 0
+ {"ipx-compression", 1, setipxcompression}, /* IPX compression number */
+#endif
+ {"ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */
+ {"+ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */
+#endif /* IPX_CHANGE */
+
+#ifdef MSLANMAN
+ {"ms-lanman", 0, setmslanman}, /* Use LanMan psswd when using MS-CHAP */
+#endif
+
{NULL, 0, NULL}
};
@@ -238,7 +422,7 @@ static struct cmd {
static char *usage_string = "\
pppd version %s patch level %d%s\n\
-Usage: %s [ arguments ], where arguments are:\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\
@@ -251,24 +435,27 @@ Usage: %s [ arguments ], where arguments are:\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\
- netmask <n> Set interface netmask to <n>\n\
See pppd(8) for more options.\n\
";
+static char *current_option; /* the name of the option being parsed */
+static int privileged_option; /* set iff the current option came from root */
+static char *option_source; /* string saying where the option came from */
/*
- * parse_args - parse a string of arguments, from the command
- * line or from a file.
+ * parse_args - parse a string of arguments from the command line.
*/
int
parse_args(argc, argv)
int argc;
char **argv;
{
- char *arg, *val;
+ char *arg;
struct cmd *cmdp;
int ret;
+ privileged_option = privileged;
+ option_source = "command line";
while (argc > 0) {
arg = *argv++;
--argc;
@@ -282,9 +469,10 @@ parse_args(argc, argv)
if (cmdp->cmd_name != NULL) {
if (argc < cmdp->num_args) {
- fprintf(stderr, "Too few parameters for command %s\n", arg);
+ option_error("too few parameters for option %s", arg);
return 0;
}
+ current_option = arg;
if (!(*cmdp->cmd_func)(argv))
return 0;
argc -= cmdp->num_args;
@@ -294,10 +482,10 @@ parse_args(argc, argv)
/*
* Maybe a tty name, speed or IP address?
*/
- if ((ret = setdevname(arg)) == 0
+ if ((ret = setdevname(arg, 0)) == 0
&& (ret = setspeed(arg)) == 0
&& (ret = setipaddr(arg)) == 0) {
- fprintf(stderr, "%s: unrecognized command\n", arg);
+ option_error("unrecognized option '%s'", arg);
usage();
return 0;
}
@@ -309,12 +497,75 @@ parse_args(argc, argv)
}
/*
+ * scan_args - scan the command line arguments to get the tty name,
+ * if specified.
+ */
+void
+scan_args(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *arg;
+ struct cmd *cmdp;
+
+ while (argc > 0) {
+ arg = *argv++;
+ --argc;
+
+ /* Skip options and their arguments */
+ for (cmdp = cmds; cmdp->cmd_name; cmdp++)
+ if (!strcmp(arg, cmdp->cmd_name))
+ break;
+
+ if (cmdp->cmd_name != NULL) {
+ argc -= cmdp->num_args;
+ argv += cmdp->num_args;
+ continue;
+ }
+
+ /* Check if it's a tty name and copy it if so */
+ (void) setdevname(arg, 1);
+ }
+}
+
+/*
* usage - print out a message telling how to use the program.
*/
+void
usage()
{
- fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
- progname);
+ if (phase == PHASE_INITIALIZE)
+ fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
+ progname);
+}
+
+/*
+ * showhelp - print out usage message and exit.
+ */
+static int
+showhelp(argv)
+ char **argv;
+{
+ if (phase == PHASE_INITIALIZE) {
+ usage();
+ exit(0);
+ }
+ return 0;
+}
+
+/*
+ * showversion - print out the version number and exit.
+ */
+static int
+showversion(argv)
+ char **argv;
+{
+ if (phase == PHASE_INITIALIZE) {
+ fprintf(stderr, "pppd version %s patch level %d%s\n",
+ VERSION, PATCHLEVEL, IMPLEMENTATION);
+ exit(0);
+ }
+ return 0;
}
/*
@@ -322,14 +573,16 @@ usage()
* and interpret them.
*/
int
-options_from_file(filename, must_exist, check_prot)
+options_from_file(filename, must_exist, check_prot, priv)
char *filename;
int must_exist;
int check_prot;
+ int priv;
{
FILE *f;
int i, newline, ret;
struct cmd *cmdp;
+ int oldpriv;
char *argv[MAXARGS];
char args[MAXARGS][MAXWORDLEN];
char cmd[MAXWORDLEN];
@@ -337,15 +590,18 @@ options_from_file(filename, must_exist, check_prot)
if ((f = fopen(filename, "r")) == NULL) {
if (!must_exist && errno == ENOENT)
return 1;
- perror(filename);
+ option_error("Can't open options file %s: %m", filename);
return 0;
}
if (check_prot && !readable(fileno(f))) {
- fprintf(stderr, "%s: access denied\n", filename);
+ option_error("Can't open options file %s: access denied", filename);
fclose(f);
return 0;
}
+ oldpriv = privileged_option;
+ privileged_option = priv;
+ ret = 0;
while (getword(f, cmd, &newline, filename)) {
/*
* First see if it's a command.
@@ -357,36 +613,38 @@ options_from_file(filename, must_exist, check_prot)
if (cmdp->cmd_name != NULL) {
for (i = 0; i < cmdp->num_args; ++i) {
if (!getword(f, args[i], &newline, filename)) {
- fprintf(stderr,
- "In file %s: too few parameters for command %s\n",
- filename, cmd);
- fclose(f);
- return 0;
+ option_error(
+ "In file %s: too few parameters for option '%s'",
+ filename, cmd);
+ goto err;
}
argv[i] = args[i];
}
- if (!(*cmdp->cmd_func)(argv)) {
- fclose(f);
- return 0;
- }
+ current_option = cmd;
+ if (!(*cmdp->cmd_func)(argv))
+ goto err;
} else {
/*
* Maybe a tty name, speed or IP address?
*/
- if ((ret = setdevname(cmd)) == 0
- && (ret = setspeed(cmd)) == 0
- && (ret = setipaddr(cmd)) == 0) {
- fprintf(stderr, "In file %s: unrecognized command %s\n",
- filename, cmd);
- fclose(f);
- return 0;
+ if ((i = setdevname(cmd, 0)) == 0
+ && (i = setspeed(cmd)) == 0
+ && (i = setipaddr(cmd)) == 0) {
+ option_error("In file %s: unrecognized option '%s'",
+ filename, cmd);
+ goto err;
}
- if (ret < 0) /* error */
- return 0;
+ if (i < 0) /* error */
+ goto err;
}
}
- return 1;
+ ret = 1;
+
+err:
+ fclose(f);
+ privileged_option = oldpriv;
+ return ret;
}
/*
@@ -410,7 +668,7 @@ options_from_user()
strcpy(path, user);
strcat(path, "/");
strcat(path, file);
- ret = options_from_file(path, 0, 1);
+ ret = options_from_file(path, 0, 1, privileged);
free(path);
return ret;
}
@@ -422,27 +680,53 @@ options_from_user()
int
options_for_tty()
{
- char *dev, *path;
+ char *dev, *path, *p;
int ret;
- dev = strrchr(devname, '/');
- if (dev == NULL)
- dev = devname;
- else
- ++dev;
+ dev = devnam;
+ if (strncmp(dev, "/dev/", 5) == 0)
+ dev += 5;
if (strcmp(dev, "tty") == 0)
return 1; /* don't look for /etc/ppp/options.tty */
path = malloc(strlen(_PATH_TTYOPT) + strlen(dev) + 1);
if (path == NULL)
novm("tty init file name");
strcpy(path, _PATH_TTYOPT);
- strcat(path, dev);
- ret = options_from_file(path, 0, 0);
+ /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
+ for (p = path + strlen(path); *dev != 0; ++dev)
+ *p++ = (*dev == '/'? '.': *dev);
+ *p = 0;
+ ret = options_from_file(path, 0, 0, 1);
free(path);
return ret;
}
/*
+ * option_error - print a message about an error in an option.
+ * The message is logged, and also sent to
+ * stderr if phase == PHASE_INITIALIZE.
+ */
+void
+option_error __V((char *fmt, ...))
+{
+ va_list args;
+ char buf[256];
+
+#if __STDC__
+ va_start(args, fmt);
+#else
+ char *fmt;
+ va_start(args);
+ fmt = va_arg(args, char *);
+#endif
+ vfmtmsg(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ if (phase == PHASE_INITIALIZE)
+ fprintf(stderr, "%s: %s\n", progname, buf);
+ syslog(LOG_ERR, "%s", buf);
+}
+
+/*
* readable - check if a file is readable by the real user.
*/
static int
@@ -472,7 +756,7 @@ readable(fd)
/*
* Read a word from a file.
- * Words are delimited by white-space or by quotes (").
+ * Words are delimited by white-space or by quotes (" or ').
* Quotes, white-space and \ may be escaped with \.
* \<newline> is ignored.
*/
@@ -484,112 +768,253 @@ getword(f, word, newlinep, filename)
char *filename;
{
int c, len, escape;
- int quoted;
+ int quoted, comment;
+ int value, digit, got, n;
+
+#define isoctal(c) ((c) >= '0' && (c) < '8')
*newlinep = 0;
len = 0;
escape = 0;
- quoted = 0;
+ comment = 0;
/*
- * First skip white-space and comments
+ * First skip white-space and comments.
*/
- while ((c = getc(f)) != EOF) {
+ 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 == '\\') {
- /*
- * \<newline> is ignored; \ followed by anything else
- * starts a word.
- */
- if ((c = getc(f)) == '\n')
- continue;
- word[len++] = '\\';
escape = 1;
- break;
+ continue;
}
- if (c == '\n')
- *newlinep = 1; /* next word starts a line */
- else if (c == '#') {
- /* comment - ignore until EOF or \n */
- while ((c = getc(f)) != EOF && c != '\n')
- ;
- if (c == EOF)
- break;
- *newlinep = 1;
- } else if (!isspace(c))
+
+ /*
+ * 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;
}
/*
- * End of file or error - fail
+ * Save the delimiter for quoted strings.
*/
- if (c == EOF) {
- if (ferror(f)) {
- perror(filename);
- die(1);
- }
- return 0;
- }
+ if (!escape && (c == '"' || c == '\'')) {
+ quoted = c;
+ c = getc(f);
+ } else
+ quoted = 0;
- for (;;) {
- /*
- * Is this character escaped by \ ?
- */
+ /*
+ * Process characters until the end of the word.
+ */
+ while (c != EOF) {
if (escape) {
- if (c == '\n')
- --len; /* ignore \<newline> */
- else if (c == '"' || isspace(c) || c == '\\')
- word[len-1] = c; /* put special char in word */
- else {
- if (len < MAXWORDLEN-1)
- word[len] = c;
- ++len;
- }
+ /*
+ * This character is escaped: backslash-newline is ignored,
+ * various other characters indicate particular values
+ * as for C backslash-escapes.
+ */
escape = 0;
- } else if (c == '"') {
- quoted = !quoted;
- } else if (!quoted && (isspace(c) || c == '#')) {
- ungetc(c, f);
- break;
- } else {
+ 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] = c;
+ word[len] = value;
++len;
- if (c == '\\')
- escape = 1;
+
+ if (!got)
+ c = getc(f);
+ continue;
+
}
- if ((c = getc(f)) == EOF)
- break;
+
+ /*
+ * 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);
}
- if (ferror(f)) {
- perror(filename);
- die(1);
+ /*
+ * 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) {
- word[MAXWORDLEN-1] = 0;
- fprintf(stderr, "%s: warning: word in file %s too long (%.20s...)\n",
- progname, filename, word);
- } else
- word[len] = 0;
+ 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 a numeric parameter for an option
+ * number_option - parse an unsigned numeric parameter for an option.
*/
static int
number_option(str, valp, base)
char *str;
- long *valp;
+ u_int32_t *valp;
int base;
{
char *ptr;
- *valp = strtol(str, &ptr, base);
+ *valp = strtoul(str, &ptr, base);
if (ptr == str) {
- fprintf(stderr, "%s: invalid number: %s\n", progname, str);
+ option_error("invalid numeric parameter '%s' for %s option",
+ str, current_option);
return 0;
}
return 1;
@@ -606,7 +1031,7 @@ int_option(str, valp)
char *str;
int *valp;
{
- long v;
+ u_int32_t v;
if (!number_option(str, &v, 0))
return 0;
@@ -616,7 +1041,7 @@ int_option(str, valp)
/*
- * The following procedures execute commands.
+ * The following procedures parse options.
*/
/*
@@ -626,14 +1051,60 @@ static int
readfile(argv)
char **argv;
{
- return options_from_file(*argv, 1, 1);
+ return options_from_file(*argv, 1, 1, privileged_option);
}
/*
+ * callfile - take commands from /etc/ppp/peers/<name>.
+ * Name may not contain /../, start with / or ../, or end in /..
+ */
+static int
+callfile(argv)
+ char **argv;
+{
+ char *fname, *arg, *p;
+ int l, ok;
+
+ arg = *argv;
+ ok = 1;
+ if (arg[0] == '/' || arg[0] == 0)
+ ok = 0;
+ else {
+ for (p = arg; *p != 0; ) {
+ if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
+ ok = 0;
+ break;
+ }
+ while (*p != '/' && *p != 0)
+ ++p;
+ if (*p == '/')
+ ++p;
+ }
+ }
+ if (!ok) {
+ option_error("call option value may not contain .. or start with /");
+ return 0;
+ }
+
+ l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
+ if ((fname = (char *) malloc(l)) == NULL)
+ novm("call file name");
+ strcpy(fname, _PATH_PEERFILES);
+ strcat(fname, arg);
+
+ ok = options_from_file(fname, 1, 1, 1);
+
+ free(fname);
+ return ok;
+}
+
+
+/*
* setdebug - Set debug (command line argument).
*/
static int
-setdebug()
+setdebug(argv)
+ char **argv;
{
debug++;
return (1);
@@ -649,16 +1120,67 @@ setkdebug(argv)
return int_option(*argv, &kdebugflag);
}
+#ifdef PPP_FILTER
+/*
+ * setpdebug - Set libpcap debugging level.
+ */
+static int
+setpdebug(argv)
+ char **argv;
+{
+ return int_option(*argv, &dflag);
+}
+
+/*
+ * setpassfilter - Set the pass filter for packets
+ */
+static int
+setpassfilter(argv)
+ char **argv;
+{
+ pc.linktype = DLT_PPP;
+ pc.snapshot = PPP_HDRLEN;
+
+ if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
+ return 1;
+ option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
+ return 0;
+}
+
+/*
+ * setactivefilter - Set the active filter for packets
+ */
+static int
+setactivefilter(argv)
+ char **argv;
+{
+ pc.linktype = DLT_PPP;
+ pc.snapshot = PPP_HDRLEN;
+
+ if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
+ return 1;
+ option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
+ return 0;
+}
+#endif
+
/*
* noopt - Disable all options.
*/
static int
-noopt()
+noopt(argv)
+ char **argv;
{
BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
+
+#ifdef IPX_CHANGE
+ BZERO((char *) &ipxcp_wantoptions[0], sizeof (struct ipxcp_options));
+ BZERO((char *) &ipxcp_allowoptions[0], sizeof (struct ipxcp_options));
+#endif /* IPX_CHANGE */
+
return (1);
}
@@ -666,7 +1188,8 @@ noopt()
* noaccomp - Disable Address/Control field compression negotiation.
*/
static int
-noaccomp()
+noaccomp(argv)
+ char **argv;
{
lcp_wantoptions[0].neg_accompression = 0;
lcp_allowoptions[0].neg_accompression = 0;
@@ -678,7 +1201,8 @@ noaccomp()
* noasyncmap - Disable async map negotiation.
*/
static int
-noasyncmap()
+noasyncmap(argv)
+ char **argv;
{
lcp_wantoptions[0].neg_asyncmap = 0;
lcp_allowoptions[0].neg_asyncmap = 0;
@@ -687,13 +1211,13 @@ noasyncmap()
/*
- * noipaddr - Disable IP address negotiation.
+ * noip - Disable IP and IPCP.
*/
static int
-noipaddr()
+noip(argv)
+ char **argv;
{
- ipcp_wantoptions[0].neg_addr = 0;
- ipcp_allowoptions[0].neg_addr = 0;
+ ipcp_protent.enabled_flag = 0;
return (1);
}
@@ -702,7 +1226,8 @@ noipaddr()
* nomagicnumber - Disable magic number negotiation.
*/
static int
-nomagicnumber()
+nomagicnumber(argv)
+ char **argv;
{
lcp_wantoptions[0].neg_magicnumber = 0;
lcp_allowoptions[0].neg_magicnumber = 0;
@@ -714,7 +1239,8 @@ nomagicnumber()
* nomru - Disable mru negotiation.
*/
static int
-nomru()
+nomru(argv)
+ char **argv;
{
lcp_wantoptions[0].neg_mru = 0;
lcp_allowoptions[0].neg_mru = 0;
@@ -729,7 +1255,7 @@ static int
setmru(argv)
char **argv;
{
- long mru;
+ u_int32_t mru;
if (!number_option(*argv, &mru, 0))
return 0;
@@ -746,25 +1272,41 @@ static int
setmtu(argv)
char **argv;
{
- long mtu;
+ u_int32_t mtu;
if (!number_option(*argv, &mtu, 0))
return 0;
if (mtu < MINMRU || mtu > MAXMRU) {
- fprintf(stderr, "mtu option value of %d is too %s\n", mtu,
- (mtu < MINMRU? "small": "large"));
+ option_error("mtu option value of %u is too %s", mtu,
+ (mtu < MINMRU? "small": "large"));
return 0;
}
lcp_allowoptions[0].mru = mtu;
return (1);
}
+#ifdef CBCP_SUPPORT
+static int
+setcbcp(argv)
+ char **argv;
+{
+ lcp_wantoptions[0].neg_cbcp = 1;
+ cbcp_protent.enabled_flag = 1;
+ cbcp[0].us_number = strdup(*argv);
+ if (cbcp[0].us_number == 0)
+ novm("callback number");
+ cbcp[0].us_type |= (1 << CB_CONF_USER);
+ cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
+ return (1);
+}
+#endif
/*
* nopcomp - Disable Protocol field compression negotiation.
*/
static int
-nopcomp()
+nopcomp(argv)
+ char **argv;
{
lcp_wantoptions[0].neg_pcompression = 0;
lcp_allowoptions[0].neg_pcompression = 0;
@@ -777,7 +1319,8 @@ nopcomp()
* LCP configure-requests).
*/
static int
-setpassive()
+setpassive(argv)
+ char **argv;
{
lcp_wantoptions[0].passive = 1;
return (1);
@@ -789,7 +1332,8 @@ setpassive()
* until we get one from the peer).
*/
static int
-setsilent()
+setsilent(argv)
+ char **argv;
{
lcp_wantoptions[0].silent = 1;
return 1;
@@ -800,9 +1344,10 @@ setsilent()
* nopap - Disable PAP authentication with peer.
*/
static int
-nopap()
+nopap(argv)
+ char **argv;
{
- lcp_allowoptions[0].neg_upap = 0;
+ refuse_pap = 1;
return (1);
}
@@ -811,13 +1356,15 @@ nopap()
* reqpap - Require PAP authentication from peer.
*/
static int
-reqpap()
+reqpap(argv)
+ char **argv;
{
lcp_wantoptions[0].neg_upap = 1;
- auth_required = 1;
+ setauth(NULL);
+ return 1;
}
-
+#if OLD_OPTIONS
/*
* setupapfile - specifies UPAP info for authenticating with peer.
*/
@@ -832,11 +1379,11 @@ setupapfile(argv)
/* open user info file */
if ((ufile = fopen(*argv, "r")) == NULL) {
- fprintf(stderr, "unable to open user login data file %s\n", *argv);
+ option_error("unable to open user login data file %s", *argv);
return 0;
}
if (!readable(fileno(ufile))) {
- fprintf(stderr, "%s: access denied\n", *argv);
+ option_error("%s: access denied", *argv);
return 0;
}
check_access(ufile, *argv);
@@ -844,7 +1391,7 @@ setupapfile(argv)
/* get username */
if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
|| fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
- fprintf(stderr, "Unable to read user login data file %s.\n", *argv);
+ option_error("unable to read user login data file %s", *argv);
return 0;
}
fclose(ufile);
@@ -859,15 +1406,16 @@ setupapfile(argv)
return (1);
}
-
+#endif
/*
* nochap - Disable CHAP authentication with peer.
*/
static int
-nochap()
+nochap(argv)
+ char **argv;
{
- lcp_allowoptions[0].neg_chap = 0;
+ refuse_chap = 1;
return (1);
}
@@ -876,10 +1424,11 @@ nochap()
* reqchap - Require CHAP authentication from peer.
*/
static int
-reqchap()
+reqchap(argv)
+ char **argv;
{
lcp_wantoptions[0].neg_chap = 1;
- auth_required = 1;
+ setauth(NULL);
return (1);
}
@@ -888,7 +1437,8 @@ reqchap()
* setnovj - disable vj compression
*/
static int
-setnovj()
+setnovj(argv)
+ char **argv;
{
ipcp_wantoptions[0].neg_vj = 0;
ipcp_allowoptions[0].neg_vj = 0;
@@ -900,10 +1450,12 @@ setnovj()
* setnovjccomp - disable VJ connection-ID compression
*/
static int
-setnovjccomp()
+setnovjccomp(argv)
+ char **argv;
{
ipcp_wantoptions[0].cflag = 0;
ipcp_allowoptions[0].cflag = 0;
+ return 1;
}
@@ -919,7 +1471,7 @@ setvjslots(argv)
if (!int_option(*argv, &value))
return 0;
if (value < 2 || value > 16) {
- fprintf(stderr, "pppd: vj-max-slots value must be between 2 and 16\n");
+ option_error("vj-max-slots value must be between 2 and 16");
return 0;
}
ipcp_wantoptions [0].maxslotindex =
@@ -937,8 +1489,10 @@ setconnector(argv)
{
connector = strdup(*argv);
if (connector == NULL)
- novm("connector string");
-
+ novm("connect script");
+ connector_info.priv = privileged_option;
+ connector_info.source = option_source;
+
return (1);
}
@@ -951,11 +1505,51 @@ setdisconnector(argv)
{
disconnector = strdup(*argv);
if (disconnector == NULL)
- novm("disconnector string");
+ novm("disconnect script");
+ disconnector_info.priv = privileged_option;
+ disconnector_info.source = option_source;
return (1);
}
+/*
+ * setwelcomer - Set a program to welcome a client after connection
+ */
+static int
+setwelcomer(argv)
+ char **argv;
+{
+ welcomer = strdup(*argv);
+ if (welcomer == NULL)
+ novm("welcome script");
+ welcomer_info.priv = privileged_option;
+ welcomer_info.source = option_source;
+
+ return (1);
+}
+
+/*
+ * setmaxconnect - Set the maximum connect time
+ */
+static int
+setmaxconnect(argv)
+ char **argv;
+{
+ int value;
+
+ if (!int_option(*argv, &value))
+ return 0;
+ if (value < 0) {
+ option_error("maxconnect time must be positive");
+ return 0;
+ }
+ if (maxconnect > 0 && (value == 0 || value > maxconnect)) {
+ option_error("maxconnect time cannot be increased");
+ return 0;
+ }
+ maxconnect = value;
+ return 1;
+}
/*
* setdomain - Set domain name to append to hostname
@@ -964,7 +1558,16 @@ static int
setdomain(argv)
char **argv;
{
- strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
+ 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);
}
@@ -977,7 +1580,7 @@ static int
setasyncmap(argv)
char **argv;
{
- long asyncmap;
+ u_int32_t asyncmap;
if (!number_option(*argv, &asyncmap, 16))
return 0;
@@ -1002,12 +1605,13 @@ setescape(argv)
while (*p) {
n = strtol(p, &endp, 16);
if (p == endp) {
- fprintf(stderr, "%s: invalid hex number: %s\n", progname, p);
+ option_error("escape parameter contains invalid hex number '%s'",
+ p);
return 0;
}
p = endp;
- if (n < 0 || 0x20 <= n && n <= 0x3F || n == 0x5E || n > 0xFF) {
- fprintf(stderr, "%s: can't escape character 0x%x\n", n);
+ if (n < 0 || (0x20 <= n && n <= 0x3F) || n == 0x5E || n > 0xFF) {
+ option_error("can't escape character 0x%x", n);
ret = 0;
} else
xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
@@ -1039,14 +1643,17 @@ setspeed(arg)
/*
* setdevname - Set the device name.
*/
-int
-setdevname(cp)
+static int
+setdevname(cp, quiet)
char *cp;
+ int quiet;
{
struct stat statbuf;
- char *tty, *ttyname();
char dev[MAXPATHLEN];
-
+
+ if (*cp == 0)
+ return 0;
+
if (strncmp("/dev/", cp, 5) != 0) {
strcpy(dev, "/dev/");
strncat(dev, cp, MAXPATHLEN - 5);
@@ -1058,15 +1665,17 @@ setdevname(cp)
* Check if there is a device by this name.
*/
if (stat(cp, &statbuf) < 0) {
- if (errno == ENOENT)
+ if (errno == ENOENT || quiet)
return 0;
- syslog(LOG_ERR, cp);
+ option_error("Couldn't stat %s: %m", cp);
return -1;
}
-
- (void) strncpy(devname, cp, MAXPATHLEN);
- devname[MAXPATHLEN-1] = 0;
+
+ (void) strncpy(devnam, cp, MAXPATHLEN);
+ devnam[MAXPATHLEN-1] = 0;
default_device = FALSE;
+ devnam_info.priv = privileged_option;
+ devnam_info.source = option_source;
return 1;
}
@@ -1075,19 +1684,19 @@ setdevname(cp)
/*
* setipaddr - Set the IP address
*/
-int
+static int
setipaddr(arg)
char *arg;
{
struct hostent *hp;
- char *colon, *index();
- u_long local, remote;
+ char *colon;
+ u_int32_t local, remote;
ipcp_options *wo = &ipcp_wantoptions[0];
/*
* IP address pair separated by ":".
*/
- if ((colon = index(arg, ':')) == NULL)
+ if ((colon = strchr(arg, ':')) == NULL)
return 0;
/*
@@ -1097,18 +1706,14 @@ setipaddr(arg)
*colon = '\0';
if ((local = inet_addr(arg)) == -1) {
if ((hp = gethostbyname(arg)) == NULL) {
- fprintf(stderr, "unknown host: %s\n", arg);
+ option_error("unknown host: %s", arg);
return -1;
} else {
- local = *(long *)hp->h_addr;
- if (our_name[0] == 0) {
- strncpy(our_name, arg, MAXNAMELEN);
- our_name[MAXNAMELEN-1] = 0;
- }
+ local = *(u_int32_t *)hp->h_addr;
}
}
if (bad_ip_adrs(local)) {
- fprintf(stderr, "bad local IP address %s\n", ip_ntoa(local));
+ option_error("bad local IP address %s", ip_ntoa(local));
return -1;
}
if (local != 0)
@@ -1122,10 +1727,10 @@ setipaddr(arg)
if (*++colon != '\0') {
if ((remote = inet_addr(colon)) == -1) {
if ((hp = gethostbyname(colon)) == NULL) {
- fprintf(stderr, "unknown host: %s\n", colon);
+ option_error("unknown host: %s", colon);
return -1;
} else {
- remote = *(long *)hp->h_addr;
+ remote = *(u_int32_t *)hp->h_addr;
if (remote_name[0] == 0) {
strncpy(remote_name, colon, MAXNAMELEN);
remote_name[MAXNAMELEN-1] = 0;
@@ -1133,7 +1738,7 @@ setipaddr(arg)
}
}
if (bad_ip_adrs(remote)) {
- fprintf(stderr, "bad remote IP address %s\n", ip_ntoa(remote));
+ option_error("bad remote IP address %s", ip_ntoa(remote));
return -1;
}
if (remote != 0)
@@ -1148,7 +1753,8 @@ setipaddr(arg)
* setnoipdflt - disable setipdefault()
*/
static int
-setnoipdflt()
+setnoipdflt(argv)
+ char **argv;
{
disable_defaultip = 1;
return 1;
@@ -1159,7 +1765,8 @@ setnoipdflt()
* setipcpaccl - accept peer's idea of our address
*/
static int
-setipcpaccl()
+setipcpaccl(argv)
+ char **argv;
{
ipcp_wantoptions[0].accept_local = 1;
return 1;
@@ -1170,7 +1777,8 @@ setipcpaccl()
* setipcpaccr - accept peer's idea of its address
*/
static int
-setipcpaccr()
+setipcpaccr(argv)
+ char **argv;
{
ipcp_wantoptions[0].accept_remote = 1;
return 1;
@@ -1178,46 +1786,46 @@ setipcpaccr()
/*
- * setipdefault - default our local IP address based on our hostname.
- */
-void
-setipdefault()
-{
- struct hostent *hp;
- u_long local;
- ipcp_options *wo = &ipcp_wantoptions[0];
-
- /*
- * If local IP address already given, don't bother.
- */
- if (wo->ouraddr != 0 || disable_defaultip)
- return;
-
- /*
- * Look up our hostname (possibly with domain name appended)
- * and take the first IP address as our local IP address.
- * If there isn't an IP address for our hostname, too bad.
- */
- wo->accept_local = 1; /* don't insist on this default value */
- if ((hp = gethostbyname(hostname)) == NULL)
- return;
- local = *(long *)hp->h_addr;
- if (local != 0 && !bad_ip_adrs(local))
- wo->ouraddr = local;
-}
-
-
-/*
* setnetmask - set the netmask to be used on the interface.
*/
static int
setnetmask(argv)
char **argv;
{
- u_long mask;
+ 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 < 0 || 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 ((mask = inet_addr(*argv)) == -1 || (netmask & ~mask) != 0) {
- fprintf(stderr, "Invalid netmask %s\n", *argv);
+ if (*p != 0 || (netmask & ~mask) != 0) {
+ option_error("invalid netmask value '%s'", *argv);
return 0;
}
@@ -1225,63 +1833,77 @@ setnetmask(argv)
return (1);
}
-/*
- * Return user specified netmask. A value of zero means no netmask has
- * been set.
- */
-/* ARGSUSED */
-u_long
-GetMask(addr)
- u_long addr;
+static int
+setcrtscts(argv)
+ char **argv;
{
- return(netmask);
+ crtscts = 1;
+ return (1);
}
-
static int
-setcrtscts()
+setnocrtscts(argv)
+ char **argv;
{
- crtscts = 1;
+ crtscts = -1;
return (1);
}
static int
-setxonxoff()
+setxonxoff(argv)
+ char **argv;
{
- crtscts = 2;
+ lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */
+ lcp_wantoptions[0].neg_asyncmap = 1;
+
+ crtscts = -2;
return (1);
}
static int
-setnodetach()
+setnodetach(argv)
+ char **argv;
{
nodetach = 1;
return (1);
}
static int
-setmodem()
+setdemand(argv)
+ char **argv;
+{
+ demand = 1;
+ persist = 1;
+ return 1;
+}
+
+static int
+setmodem(argv)
+ char **argv;
{
modem = 1;
return 1;
}
static int
-setlocal()
+setlocal(argv)
+ char **argv;
{
modem = 0;
return 1;
}
static int
-setlock()
+setlock(argv)
+ char **argv;
{
lockflag = 1;
return 1;
}
static int
-setusehostname()
+setusehostname(argv)
+ char **argv;
{
usehostname = 1;
return 1;
@@ -1291,10 +1913,12 @@ static int
setname(argv)
char **argv;
{
- if (our_name[0] == 0) {
- strncpy(our_name, argv[0], MAXNAMELEN);
- our_name[MAXNAMELEN-1] = 0;
+ if (!privileged_option) {
+ option_error("using the name option requires root privilege");
+ return 0;
}
+ strncpy(our_name, argv[0], MAXNAMELEN);
+ our_name[MAXNAMELEN-1] = 0;
return 1;
}
@@ -1317,35 +1941,91 @@ setremote(argv)
}
static int
-setauth()
+setauth(argv)
+ char **argv;
{
auth_required = 1;
+ if (privileged_option > auth_req_info.priv) {
+ auth_req_info.priv = privileged_option;
+ auth_req_info.source = option_source;
+ }
+ return 1;
+}
+
+static int
+setnoauth(argv)
+ char **argv;
+{
+ if (auth_required && privileged_option < auth_req_info.priv) {
+ option_error("cannot override auth option set by %s",
+ auth_req_info.source);
+ return 0;
+ }
+ auth_required = 0;
return 1;
}
static int
-setdefaultroute()
+setdefaultroute(argv)
+ char **argv;
{
+ if (!ipcp_allowoptions[0].default_route) {
+ option_error("defaultroute option is disabled");
+ return 0;
+ }
ipcp_wantoptions[0].default_route = 1;
return 1;
}
static int
-setproxyarp()
+setnodefaultroute(argv)
+ char **argv;
+{
+ ipcp_allowoptions[0].default_route = 0;
+ ipcp_wantoptions[0].default_route = 0;
+ return 1;
+}
+
+static int
+setproxyarp(argv)
+ char **argv;
{
+ if (!ipcp_allowoptions[0].proxy_arp) {
+ option_error("proxyarp option is disabled");
+ return 0;
+ }
ipcp_wantoptions[0].proxy_arp = 1;
return 1;
}
static int
-setpersist()
+setnoproxyarp(argv)
+ char **argv;
+{
+ ipcp_wantoptions[0].proxy_arp = 0;
+ ipcp_allowoptions[0].proxy_arp = 0;
+ return 1;
+}
+
+static int
+setpersist(argv)
+ char **argv;
{
persist = 1;
return 1;
}
static int
-setdologin()
+setnopersist(argv)
+ char **argv;
+{
+ persist = 0;
+ return 1;
+}
+
+static int
+setdologin(argv)
+ char **argv;
{
uselogin = 1;
return 1;
@@ -1379,74 +2059,495 @@ setlcptimeout(argv)
return int_option(*argv, &lcp_fsm[0].timeouttime);
}
-static int setlcpterm(argv)
+static int
+setlcpterm(argv)
char **argv;
{
return int_option(*argv, &lcp_fsm[0].maxtermtransmits);
}
-static int setlcpconf(argv)
+static int
+setlcpconf(argv)
char **argv;
{
return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits);
}
-static int setlcpfails(argv)
+static int
+setlcpfails(argv)
char **argv;
{
return int_option(*argv, &lcp_fsm[0].maxnakloops);
}
-static int setipcptimeout(argv)
+static int
+setipcptimeout(argv)
char **argv;
{
return int_option(*argv, &ipcp_fsm[0].timeouttime);
}
-static int setipcpterm(argv)
+static int
+setipcpterm(argv)
char **argv;
{
return int_option(*argv, &ipcp_fsm[0].maxtermtransmits);
}
-static int setipcpconf(argv)
+static int
+setipcpconf(argv)
char **argv;
{
return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits);
}
-static int setipcpfails(argv)
+static int
+setipcpfails(argv)
char **argv;
{
return int_option(*argv, &lcp_fsm[0].maxnakloops);
}
-static int setpaptimeout(argv)
+static int
+setpaptimeout(argv)
char **argv;
{
return int_option(*argv, &upap[0].us_timeouttime);
}
-static int setpapreqs(argv)
+static int
+setpapreqtime(argv)
+ char **argv;
+{
+ return int_option(*argv, &upap[0].us_reqtimeout);
+}
+
+static int
+setpapreqs(argv)
char **argv;
{
return int_option(*argv, &upap[0].us_maxtransmits);
}
-static int setchaptimeout(argv)
+static int
+setchaptimeout(argv)
char **argv;
{
return int_option(*argv, &chap[0].timeouttime);
}
-static int setchapchal(argv)
+static int
+setchapchal(argv)
char **argv;
{
return int_option(*argv, &chap[0].max_transmits);
}
-static int setchapintv(argv)
+static int
+setchapintv(argv)
char **argv;
{
return int_option(*argv, &chap[0].chal_interval);
}
+
+static int
+noccp(argv)
+ char **argv;
+{
+ ccp_protent.enabled_flag = 0;
+ return 1;
+}
+
+static int
+setbsdcomp(argv)
+ char **argv;
+{
+ int rbits, abits;
+ char *str, *endp;
+
+ str = *argv;
+ abits = rbits = strtol(str, &endp, 0);
+ if (endp != str && *endp == ',') {
+ str = endp + 1;
+ abits = strtol(str, &endp, 0);
+ }
+ if (*endp != 0 || endp == str) {
+ option_error("invalid parameter '%s' for bsdcomp option", *argv);
+ return 0;
+ }
+ if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
+ || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
+ option_error("bsdcomp option values must be 0 or %d .. %d",
+ BSD_MIN_BITS, BSD_MAX_BITS);
+ return 0;
+ }
+ if (rbits > 0) {
+ ccp_wantoptions[0].bsd_compress = 1;
+ ccp_wantoptions[0].bsd_bits = rbits;
+ } else
+ ccp_wantoptions[0].bsd_compress = 0;
+ if (abits > 0) {
+ ccp_allowoptions[0].bsd_compress = 1;
+ ccp_allowoptions[0].bsd_bits = abits;
+ } else
+ ccp_allowoptions[0].bsd_compress = 0;
+ return 1;
+}
+
+static int
+setnobsdcomp(argv)
+ char **argv;
+{
+ ccp_wantoptions[0].bsd_compress = 0;
+ ccp_allowoptions[0].bsd_compress = 0;
+ return 1;
+}
+
+static int
+setdeflate(argv)
+ char **argv;
+{
+ int rbits, abits;
+ char *str, *endp;
+
+ str = *argv;
+ abits = rbits = strtol(str, &endp, 0);
+ if (endp != str && *endp == ',') {
+ str = endp + 1;
+ abits = strtol(str, &endp, 0);
+ }
+ if (*endp != 0 || endp == str) {
+ option_error("invalid parameter '%s' for deflate option", *argv);
+ return 0;
+ }
+ if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
+ || (abits != 0 && (abits < DEFLATE_MIN_SIZE
+ || abits > DEFLATE_MAX_SIZE))) {
+ option_error("deflate option values must be 0 or %d .. %d",
+ DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
+ return 0;
+ }
+ if (rbits > 0) {
+ ccp_wantoptions[0].deflate = 1;
+ ccp_wantoptions[0].deflate_size = rbits;
+ } else
+ ccp_wantoptions[0].deflate = 0;
+ if (abits > 0) {
+ ccp_allowoptions[0].deflate = 1;
+ ccp_allowoptions[0].deflate_size = abits;
+ } else
+ ccp_allowoptions[0].deflate = 0;
+ return 1;
+}
+
+static int
+setnodeflate(argv)
+ char **argv;
+{
+ ccp_wantoptions[0].deflate = 0;
+ ccp_allowoptions[0].deflate = 0;
+ return 1;
+}
+
+static int
+setpred1comp(argv)
+ char **argv;
+{
+ ccp_wantoptions[0].predictor_1 = 1;
+ ccp_allowoptions[0].predictor_1 = 1;
+ return 1;
+}
+
+static int
+setnopred1comp(argv)
+ char **argv;
+{
+ ccp_wantoptions[0].predictor_1 = 0;
+ ccp_allowoptions[0].predictor_1 = 0;
+ return 1;
+}
+
+static int
+setipparam(argv)
+ char **argv;
+{
+ ipparam = strdup(*argv);
+ if (ipparam == NULL)
+ novm("ipparam string");
+
+ return 1;
+}
+
+static int
+setpapcrypt(argv)
+ char **argv;
+{
+ cryptpap = 1;
+ return 1;
+}
+
+static int
+setidle(argv)
+ char **argv;
+{
+ return int_option(*argv, &idle_time_limit);
+}
+
+static int
+setholdoff(argv)
+ char **argv;
+{
+ return int_option(*argv, &holdoff);
+}
+
+/*
+ * setdnsaddr - set the dns address(es)
+ */
+static int
+setdnsaddr(argv)
+ char **argv;
+{
+ u_int32_t dns;
+ struct hostent *hp;
+
+ dns = inet_addr(*argv);
+ if (dns == -1) {
+ if ((hp = gethostbyname(*argv)) == NULL) {
+ option_error("invalid address parameter '%s' for ms-dns option",
+ *argv);
+ return 0;
+ }
+ dns = *(u_int32_t *)hp->h_addr;
+ }
+
+ if (ipcp_allowoptions[0].dnsaddr[0] == 0) {
+ ipcp_allowoptions[0].dnsaddr[0] = dns;
+ } else {
+ ipcp_allowoptions[0].dnsaddr[1] = dns;
+ }
+
+ return (1);
+}
+
+/*
+ * setwinsaddr - set the wins address(es)
+ * This is primrarly used with the Samba package under UNIX or for pointing
+ * the caller to the existing WINS server on a Windows NT platform.
+ */
+static int
+setwinsaddr(argv)
+ char **argv;
+{
+ u_int32_t wins;
+ struct hostent *hp;
+
+ wins = inet_addr(*argv);
+ if (wins == -1) {
+ if ((hp = gethostbyname(*argv)) == NULL) {
+ option_error("invalid address parameter '%s' for ms-wins option",
+ *argv);
+ return 0;
+ }
+ wins = *(u_int32_t *)hp->h_addr;
+ }
+
+ if (ipcp_allowoptions[0].winsaddr[0] == 0) {
+ ipcp_allowoptions[0].winsaddr[0] = wins;
+ } else {
+ ipcp_allowoptions[0].winsaddr[1] = wins;
+ }
+
+ return (1);
+}
+
+#ifdef IPX_CHANGE
+static int
+setipxrouter (argv)
+ char **argv;
+{
+ ipxcp_wantoptions[0].neg_router = 1;
+ ipxcp_allowoptions[0].neg_router = 1;
+ return int_option(*argv, &ipxcp_wantoptions[0].router);
+}
+
+static int
+setipxname (argv)
+ char **argv;
+{
+ char *dest = ipxcp_wantoptions[0].name;
+ char *src = *argv;
+ int count;
+ char ch;
+
+ ipxcp_wantoptions[0].neg_name = 1;
+ ipxcp_allowoptions[0].neg_name = 1;
+ memset (dest, '\0', sizeof (ipxcp_wantoptions[0].name));
+
+ count = 0;
+ while (*src) {
+ ch = *src++;
+ if (! isalnum (ch) && ch != '_') {
+ option_error("IPX router name must be alphanumeric or _");
+ return 0;
+ }
+
+ if (count >= sizeof (ipxcp_wantoptions[0].name)) {
+ option_error("IPX router name is limited to %d characters",
+ sizeof (ipxcp_wantoptions[0].name) - 1);
+ return 0;
+ }
+
+ dest[count++] = toupper (ch);
+ }
+
+ return 1;
+}
+
+static int
+setipxcptimeout (argv)
+ char **argv;
+{
+ return int_option(*argv, &ipxcp_fsm[0].timeouttime);
+}
+
+static int
+setipxcpterm (argv)
+ char **argv;
+{
+ return int_option(*argv, &ipxcp_fsm[0].maxtermtransmits);
+}
+
+static int
+setipxcpconf (argv)
+ char **argv;
+{
+ return int_option(*argv, &ipxcp_fsm[0].maxconfreqtransmits);
+}
+
+static int
+setipxcpfails (argv)
+ char **argv;
+{
+ return int_option(*argv, &ipxcp_fsm[0].maxnakloops);
+}
+
+static int
+setipxnetwork(argv)
+ char **argv;
+{
+ u_int32_t v;
+
+ if (!number_option(*argv, &v, 16))
+ return 0;
+
+ ipxcp_wantoptions[0].our_network = (int) v;
+ ipxcp_wantoptions[0].neg_nn = 1;
+ return 1;
+}
+
+static int
+setipxanet(argv)
+ char **argv;
+{
+ ipxcp_wantoptions[0].accept_network = 1;
+ ipxcp_allowoptions[0].accept_network = 1;
+}
+
+static int
+setipxalcl(argv)
+ char **argv;
+{
+ ipxcp_wantoptions[0].accept_local = 1;
+ ipxcp_allowoptions[0].accept_local = 1;
+}
+
+static int
+setipxarmt(argv)
+ char **argv;
+{
+ ipxcp_wantoptions[0].accept_remote = 1;
+ ipxcp_allowoptions[0].accept_remote = 1;
+}
+
+static u_char *
+setipxnodevalue(src,dst)
+u_char *src, *dst;
+{
+ int indx;
+ int item;
+
+ for (;;) {
+ if (!isxdigit (*src))
+ break;
+
+ for (indx = 0; indx < 5; ++indx) {
+ dst[indx] <<= 4;
+ dst[indx] |= (dst[indx + 1] >> 4) & 0x0F;
+ }
+
+ item = toupper (*src) - '0';
+ if (item > 9)
+ item -= 7;
+
+ dst[5] = (dst[5] << 4) | item;
+ ++src;
+ }
+ return src;
+}
+
+static int
+setipxnode(argv)
+ char **argv;
+{
+ char *end;
+
+ memset (&ipxcp_wantoptions[0].our_node[0], 0, 6);
+ memset (&ipxcp_wantoptions[0].his_node[0], 0, 6);
+
+ end = setipxnodevalue (*argv, &ipxcp_wantoptions[0].our_node[0]);
+ if (*end == ':')
+ end = setipxnodevalue (++end, &ipxcp_wantoptions[0].his_node[0]);
+
+ if (*end == '\0') {
+ ipxcp_wantoptions[0].neg_node = 1;
+ return 1;
+ }
+
+ option_error("invalid parameter '%s' for ipx-node option", *argv);
+ return 0;
+}
+
+static int
+setipxproto(argv)
+ char **argv;
+{
+ ipxcp_protent.enabled_flag = 1;
+ return 1;
+}
+
+static int
+resetipxproto(argv)
+ char **argv;
+{
+ ipxcp_protent.enabled_flag = 0;
+ return 1;
+}
+#else
+
+static int
+resetipxproto(argv)
+ char **argv;
+{
+ return 1;
+}
+#endif /* IPX_CHANGE */
+
+#ifdef MSLANMAN
+static int
+setmslanman(argv)
+ char **argv;
+{
+ ms_lanman = 1;
+ return (1);
+}
+#endif
diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c
index 65c0b77..46962de 100644
--- a/usr.sbin/pppd/sys-bsd.c
+++ b/usr.sbin/pppd/sys-bsd.c
@@ -3,6 +3,7 @@
* 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
@@ -10,55 +11,202 @@
* 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.
+ * by Carnegie Mellon University and The Australian National University.
+ * The names of the Universities may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
-static char rcsid[] = "$Id: sys-bsd.c,v 1.7 1994/05/30 06:10:07 paulus Exp $";
-#endif
+static char rcsid[] = "$Id: sys-bsd.c,v 1.29 1997/11/27 06:10:04 paulus Exp $";
+/* $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */
/*
* TODO:
*/
+#include <stdio.h>
#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <signal.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
-#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#ifdef NetBSD1_2
+#include <util.h>
+#endif
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
#include <net/if.h>
+#include <net/ppp_defs.h>
#include <net/if_ppp.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#if RTM_VERSION >= 3
-#include <netinet/if_ether.h>
+#include <sys/param.h>
+#if defined(NetBSD) && (NetBSD >= 199703)
+#include <netinet/if_inarp.h>
+#else /* NetBSD 1.2D or later */
+#include <net/if_ether.h>
+#endif
#endif
#include "pppd.h"
-#include "ppp.h"
+#include "fsm.h"
+#include "ipcp.h"
-static int initdisc = -1; /* Initial TTY discipline */
-extern int kdebugflag;
+static int initdisc = -1; /* Initial TTY discipline for ppp_fd */
+static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */
+static int ppp_fd = -1; /* fd which is set to PPP discipline */
static int rtm_seq;
+static int restore_term; /* 1 => we've munged the terminal */
+static struct termios inittermios; /* Initial TTY termios */
+static struct winsize wsinfo; /* Initial window size info */
+
+static char *lock_file; /* name of lock file created */
+
+static int loop_slave = -1;
+static int loop_master;
+static char loop_name[20];
+
+static unsigned char inbuf[512]; /* buffer for chars read from loopback */
+
+static int sockfd; /* socket for doing interface ioctls */
+
+static int if_is_up; /* the interface is currently up */
+static u_int32_t ifaddrs[2]; /* local and remote addresses we set */
+static u_int32_t default_route_gateway; /* gateway addr for default route */
+static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */
+
+/* Prototypes for procedures local to this file. */
+static int dodefaultroute __P((u_int32_t, int));
+static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *));
+
+
+/*
+ * sys_init - System-dependent initialization.
+ */
+void
+sys_init()
+{
+ /* Get an internet socket for doing socket ioctl's on. */
+ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ syslog(LOG_ERR, "Couldn't create IP socket: %m");
+ die(1);
+ }
+}
+
+/*
+ * sys_cleanup - restore any system state we modified before exiting:
+ * mark the interface down, delete default route and/or proxy arp entry.
+ * This should call die() because it's called from die().
+ */
+void
+sys_cleanup()
+{
+ struct ifreq ifr;
+
+ if (if_is_up) {
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
+ && ((ifr.ifr_flags & IFF_UP) != 0)) {
+ ifr.ifr_flags &= ~IFF_UP;
+ ioctl(sockfd, SIOCSIFFLAGS, &ifr);
+ }
+ }
+ if (ifaddrs[0] != 0)
+ cifaddr(0, ifaddrs[0], ifaddrs[1]);
+ if (default_route_gateway)
+ cifdefaultroute(0, 0, default_route_gateway);
+ if (proxy_arp_addr)
+ cifproxyarp(0, proxy_arp_addr);
+}
+
+/*
+ * sys_close - Clean up in a child process before execing.
+ */
+void
+sys_close()
+{
+ close(sockfd);
+ if (loop_slave >= 0) {
+ close(loop_slave);
+ close(loop_master);
+ }
+}
+
+/*
+ * sys_check_options - check the options that the user specified
+ */
+void
+sys_check_options()
+{
+}
+
+/*
+ * ppp_available - check whether the system has any ppp interfaces
+ * (in fact we check whether we can do an ioctl on ppp0).
+ */
+int
+ppp_available()
+{
+ int s, ok;
+ struct ifreq ifr;
+ extern char *no_ppp_msg;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return 1; /* can't tell */
+
+ strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
+ ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
+ close(s);
+
+ no_ppp_msg = "\
+This system lacks kernel support for PPP. To include PPP support\n\
+in the kernel, please follow the steps detailed in the README.bsd\n\
+file in the ppp-2.2 distribution.\n";
+ return ok;
+}
+
/*
* establish_ppp - Turn the serial port into a ppp interface.
*/
void
-establish_ppp()
+establish_ppp(fd)
+ int fd;
{
int pppdisc = PPPDISC;
int x;
+ if (demand) {
+ /*
+ * Demand mode - prime the old ppp device to relinquish the unit.
+ */
+ if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
+ syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
+ die(1);
+ }
+ }
+
+ /*
+ * Save the old line discipline of fd, and set it to PPP.
+ */
if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
die(1);
@@ -68,14 +216,33 @@ establish_ppp()
die(1);
}
- /*
- * Find out which interface we were given.
- */
- if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
- die(1);
+ if (!demand) {
+ /*
+ * Find out which interface we were given.
+ */
+ if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {
+ syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
+ die(1);
+ }
+ } else {
+ /*
+ * Check that we got the same unit again.
+ */
+ if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
+ syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
+ die(1);
+ }
+ if (x != ifunit) {
+ syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
+ ifunit, x);
+ die(1);
+ }
+ x = TTYDISC;
+ ioctl(loop_slave, TIOCSETD, &x);
}
+ ppp_fd = fd;
+
/*
* Enable debug in the driver if requested.
*/
@@ -88,6 +255,50 @@ establish_ppp()
syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
}
}
+
+ /*
+ * Set device for non-blocking reads.
+ */
+ if ((initfdflags = fcntl(fd, F_GETFL)) == -1
+ || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
+ syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
+ }
+}
+
+/*
+ * restore_loop - reattach the ppp unit to the loopback.
+ */
+void
+restore_loop()
+{
+ int x;
+
+ /*
+ * Transfer the ppp interface back to the loopback.
+ */
+ if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
+ syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
+ die(1);
+ }
+ x = PPPDISC;
+ if (ioctl(loop_slave, TIOCSETD, &x) < 0) {
+ syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
+ die(1);
+ }
+
+ /*
+ * Check that we got the same unit again.
+ */
+ if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) {
+ syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
+ die(1);
+ }
+ if (x != ifunit) {
+ syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
+ ifunit, x);
+ die(1);
+ }
+ ppp_fd = loop_slave;
}
@@ -96,39 +307,222 @@ establish_ppp()
* This shouldn't call die() because it's called from die().
*/
void
-disestablish_ppp()
+disestablish_ppp(fd)
+ int fd;
+{
+ /* Reset non-blocking mode on fd. */
+ if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
+ syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
+ initfdflags = -1;
+
+ /* Restore old line discipline. */
+ if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
+ syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
+ initdisc = -1;
+
+ if (fd == ppp_fd)
+ ppp_fd = -1;
+}
+
+/*
+ * Check whether the link seems not to be 8-bit clean.
+ */
+void
+clean_check()
{
int x;
char *s;
- if (initdisc >= 0) {
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
+ s = NULL;
+ switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
+ case SC_RCV_B7_0:
+ s = "bit 7 set to 1";
+ break;
+ case SC_RCV_B7_1:
+ s = "bit 7 set to 0";
+ break;
+ case SC_RCV_EVNP:
+ s = "odd parity";
+ break;
+ case SC_RCV_ODDP:
+ s = "even parity";
+ break;
+ }
+ if (s != NULL) {
+ syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
+ syslog(LOG_WARNING, "All received characters had %s", s);
+ }
+ }
+}
+
+/*
+ * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
+ * at the requested speed, etc. If `local' is true, set CLOCAL
+ * regardless of whether the modem option was specified.
+ *
+ * For *BSD, we assume that speed_t values numerically equal bits/second.
+ */
+void
+set_up_tty(fd, local)
+ int fd, local;
+{
+ struct termios tios;
+
+ if (tcgetattr(fd, &tios) < 0) {
+ syslog(LOG_ERR, "tcgetattr: %m");
+ die(1);
+ }
+
+ if (!restore_term) {
+ inittermios = tios;
+ ioctl(fd, TIOCGWINSZ, &wsinfo);
+ }
+
+ tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
+ if (crtscts > 0 && !local)
+ tios.c_cflag |= CRTSCTS;
+ else if (crtscts < 0)
+ tios.c_cflag &= ~CRTSCTS;
+
+ tios.c_cflag |= CS8 | CREAD | HUPCL;
+ if (local || !modem)
+ tios.c_cflag |= CLOCAL;
+ tios.c_iflag = IGNBRK | IGNPAR;
+ tios.c_oflag = 0;
+ tios.c_lflag = 0;
+ tios.c_cc[VMIN] = 1;
+ tios.c_cc[VTIME] = 0;
+
+ if (crtscts == -2) {
+ tios.c_iflag |= IXON | IXOFF;
+ tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
+ tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
+ }
+
+ if (inspeed) {
+ cfsetospeed(&tios, inspeed);
+ cfsetispeed(&tios, inspeed);
+ } else {
+ inspeed = cfgetospeed(&tios);
/*
- * Check whether the link seems not to be 8-bit clean.
+ * We can't proceed if the serial port speed is 0,
+ * since that implies that the serial port is disabled.
*/
- if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
- s = NULL;
- switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
- case SC_RCV_B7_0:
- s = "bit 7 set to 1";
- break;
- case SC_RCV_B7_1:
- s = "bit 7 set to 0";
- break;
- case SC_RCV_EVNP:
- s = "odd parity";
- break;
- case SC_RCV_ODDP:
- s = "even parity";
- break;
- }
- if (s != NULL) {
- syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
- syslog(LOG_WARNING, "All received characters had %s", s);
- }
+ if (inspeed == 0) {
+ syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
+ devnam);
+ die(1);
}
- if (ioctl(fd, TIOCSETD, &initdisc) < 0)
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
}
+ baud_rate = inspeed;
+
+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
+ syslog(LOG_ERR, "tcsetattr: %m");
+ die(1);
+ }
+
+ restore_term = 1;
+}
+
+/*
+ * restore_tty - restore the terminal to the saved settings.
+ */
+void
+restore_tty(fd)
+ int fd;
+{
+ if (restore_term) {
+ if (!default_device) {
+ /*
+ * Turn off echoing, because otherwise we can get into
+ * a loop with the tty and the modem echoing to each other.
+ * We presume we are the sole user of this tty device, so
+ * when we close it, it will revert to its defaults anyway.
+ */
+ inittermios.c_lflag &= ~(ECHO | ECHONL);
+ }
+ if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
+ if (errno != ENXIO)
+ syslog(LOG_WARNING, "tcsetattr: %m");
+ ioctl(fd, TIOCSWINSZ, &wsinfo);
+ restore_term = 0;
+ }
+}
+
+/*
+ * setdtr - control the DTR line on the serial port.
+ * This is called from die(), so it shouldn't call die().
+ */
+void
+setdtr(fd, on)
+int fd, on;
+{
+ int modembits = TIOCM_DTR;
+
+ ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
+}
+
+
+/*
+ * open_ppp_loopback - open the device we use for getting
+ * packets in demand mode, and connect it to a ppp interface.
+ * Here we use a pty.
+ */
+void
+open_ppp_loopback()
+{
+ int flags;
+ struct termios tios;
+ int pppdisc = PPPDISC;
+
+ if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) {
+ syslog(LOG_ERR, "No free pty for loopback");
+ die(1);
+ }
+ SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
+
+ if (tcgetattr(loop_slave, &tios) == 0) {
+ tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
+ tios.c_cflag |= CS8 | CREAD;
+ tios.c_iflag = IGNPAR;
+ tios.c_oflag = 0;
+ tios.c_lflag = 0;
+ if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
+ syslog(LOG_WARNING, "couldn't set attributes on loopback: %m");
+ }
+
+ if ((flags = fcntl(loop_master, F_GETFL)) != -1)
+ if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
+ syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m");
+
+ ppp_fd = loop_slave;
+ if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0) {
+ syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
+ die(1);
+ }
+
+ /*
+ * Find out which interface we were given.
+ */
+ if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) {
+ syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
+ die(1);
+ }
+
+ /*
+ * Enable debug in the driver if requested.
+ */
+ if (kdebugflag) {
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
+ syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
+ } else {
+ flags |= (kdebugflag & 0xFF) * SC_DEBUG;
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
+ syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
+ }
+ }
+
}
@@ -141,13 +535,73 @@ output(unit, p, len)
u_char *p;
int len;
{
- if (unit != 0)
- MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
if (debug)
- log_packet(p, len, "sent ");
+ log_packet(p, len, "sent ", LOG_DEBUG);
+
+ if (write(ttyfd, p, len) < 0) {
+ if (errno != EIO)
+ syslog(LOG_ERR, "write: %m");
+ }
+}
+
+
+/*
+ * wait_input - wait until there is data available on ttyfd,
+ * for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+void
+wait_input(timo)
+ struct timeval *timo;
+{
+ fd_set ready;
+ int n;
+
+ FD_ZERO(&ready);
+ FD_SET(ttyfd, &ready);
+ n = select(ttyfd+1, &ready, NULL, &ready, timo);
+ if (n < 0 && errno != EINTR) {
+ syslog(LOG_ERR, "select: %m");
+ die(1);
+ }
+}
+
- if (write(fd, p, len) < 0) {
- syslog(LOG_ERR, "write: %m");
+/*
+ * wait_loop_output - wait until there is data available on the
+ * loopback, for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+void
+wait_loop_output(timo)
+ struct timeval *timo;
+{
+ fd_set ready;
+ int n;
+
+ FD_ZERO(&ready);
+ FD_SET(loop_master, &ready);
+ n = select(loop_master + 1, &ready, NULL, &ready, timo);
+ if (n < 0 && errno != EINTR) {
+ syslog(LOG_ERR, "select: %m");
+ die(1);
+ }
+}
+
+
+/*
+ * wait_time - wait for a given length of time or until a
+ * signal is received.
+ */
+void
+wait_time(timo)
+ struct timeval *timo;
+{
+ int n;
+
+ n = select(0, NULL, NULL, NULL, timo);
+ if (n < 0 && errno != EINTR) {
+ syslog(LOG_ERR, "select: %m");
die(1);
}
}
@@ -162,12 +616,10 @@ read_packet(buf)
{
int len;
- if ((len = read(fd, buf, MTU + DLLHEADERLEN)) < 0) {
- if (errno == EWOULDBLOCK) {
- MAINDEBUG((LOG_DEBUG, "read(fd): EWOULDBLOCK"));
+ if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
+ if (errno == EWOULDBLOCK || errno == EINTR)
return -1;
- }
- syslog(LOG_ERR, "read(fd): %m");
+ syslog(LOG_ERR, "read: %m");
die(1);
}
return len;
@@ -175,13 +627,41 @@ read_packet(buf)
/*
+ * get_loop_output - read characters from the loopback, form them
+ * into frames, and detect when we want to bring the real link up.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ */
+int
+get_loop_output()
+{
+ int rv = 0;
+ int n;
+
+ while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
+ if (loop_chars(inbuf, n))
+ rv = 1;
+ }
+
+ if (n == 0) {
+ syslog(LOG_ERR, "eof on loopback");
+ die(1);
+ } else if (errno != EWOULDBLOCK){
+ syslog(LOG_ERR, "read from loopback: %m");
+ die(1);
+ }
+
+ return rv;
+}
+
+
+/*
* ppp_send_config - configure the transmit characteristics of
* the ppp interface.
*/
void
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
int unit, mtu;
- u_long asyncmap;
+ u_int32_t asyncmap;
int pcomp, accomp;
{
u_int x;
@@ -189,23 +669,23 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
ifr.ifr_mtu = mtu;
- if (ioctl(s, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
+ if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
quit();
}
- if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
+ if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
quit();
}
- if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
quit();
}
x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
- if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
quit();
}
@@ -220,7 +700,7 @@ ppp_set_xaccm(unit, accm)
int unit;
ext_accm accm;
{
- if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
+ if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
}
@@ -232,31 +712,127 @@ ppp_set_xaccm(unit, accm)
void
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
int unit, mru;
- u_long asyncmap;
+ u_int32_t asyncmap;
int pcomp, accomp;
{
int x;
- if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
+ if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
quit();
}
- if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
+ if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
quit();
}
- if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
quit();
}
x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
- if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
quit();
}
}
/*
+ * ccp_test - ask kernel whether a given compression method
+ * is acceptable for use. Returns 1 if the method and parameters
+ * are OK, 0 if the method is known but the parameters are not OK
+ * (e.g. code size should be reduced), or -1 if the method is unknown.
+ */
+int
+ccp_test(unit, opt_ptr, opt_len, for_transmit)
+ int unit, opt_len, for_transmit;
+ u_char *opt_ptr;
+{
+ struct ppp_option_data data;
+
+ data.ptr = opt_ptr;
+ data.length = opt_len;
+ data.transmit = for_transmit;
+ if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
+ return 1;
+ return (errno == ENOBUFS)? 0: -1;
+}
+
+/*
+ * ccp_flags_set - inform kernel about the current state of CCP.
+ */
+void
+ccp_flags_set(unit, isopen, isup)
+ int unit, isopen, isup;
+{
+ int x;
+
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
+ return;
+ }
+ x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
+ x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
+ syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
+}
+
+/*
+ * ccp_fatal_error - returns 1 if decompression was disabled as a
+ * result of an error detected after decompression of a packet,
+ * 0 otherwise. This is necessary because of patent nonsense.
+ */
+int
+ccp_fatal_error(unit)
+ int unit;
+{
+ int x;
+
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
+ return 0;
+ }
+ return x & SC_DC_FERROR;
+}
+
+/*
+ * get_idle_time - return how long the link has been idle.
+ */
+int
+get_idle_time(u, ip)
+ int u;
+ struct ppp_idle *ip;
+{
+ return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
+}
+
+
+#ifdef PPP_FILTER
+/*
+ * set_filters - transfer the pass and active filters to the kernel.
+ */
+int
+set_filters(pass, active)
+ struct bpf_program *pass, *active;
+{
+ int ret = 1;
+
+ if (pass->bf_len > 0) {
+ if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
+ syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
+ ret = 0;
+ }
+ }
+ if (active->bf_len > 0) {
+ if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
+ syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
+ ret = 0;
+ }
+ }
+ return ret;
+}
+#endif
+
+/*
* sifvjcomp - config tcp header compression
*/
int
@@ -265,17 +841,17 @@ sifvjcomp(u, vjcomp, cidcomp, maxcid)
{
u_int x;
- if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
return 0;
}
x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
- if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
- if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
+ if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
@@ -290,25 +866,36 @@ sifup(u)
int u;
{
struct ifreq ifr;
- u_int x;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
- if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+ if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
return 0;
}
ifr.ifr_flags |= IFF_UP;
- if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+ if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
- if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
- return 0;
- }
- x |= SC_ENABLE_IP;
- if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
+ if_is_up = 1;
+ return 1;
+}
+
+/*
+ * sifnpmode - Set the mode for handling packets for a given NP.
+ */
+int
+sifnpmode(u, proto, mode)
+ int u;
+ int proto;
+ enum NPmode mode;
+{
+ struct npioctl npi;
+
+ npi.protocol = proto;
+ npi.mode = mode;
+ if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
+ syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
return 0;
}
return 1;
@@ -322,30 +909,26 @@ sifdown(u)
int u;
{
struct ifreq ifr;
- u_int x;
int rv;
+ struct npioctl npi;
rv = 1;
- if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
- rv = 0;
- } else {
- x &= ~SC_ENABLE_IP;
- if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
- rv = 0;
- }
- }
+ npi.protocol = PPP_IP;
+ npi.mode = NPMODE_ERROR;
+ ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
+ /* ignore errors, because ppp_fd might have been closed by now. */
+
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
- if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+ if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
rv = 0;
} else {
ifr.ifr_flags &= ~IFF_UP;
- if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+ if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
rv = 0;
- }
+ } else
+ if_is_up = 0;
}
return rv;
}
@@ -365,9 +948,10 @@ sifdown(u)
int
sifaddr(u, o, h, m)
int u;
- u_long o, h, m;
+ u_int32_t o, h, m;
{
struct ifaliasreq ifra;
+ struct ifreq ifr;
strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
@@ -379,13 +963,23 @@ sifaddr(u, o, h, m)
((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
} else
BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
- if (ioctl(s, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
+ BZERO(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
+ if (errno != EADDRNOTAVAIL)
+ syslog(LOG_WARNING, "Couldn't remove interface address: %m");
+ }
+ if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
if (errno != EEXIST) {
- syslog(LOG_ERR, "ioctl(SIOCAIFADDR): %m");
+ syslog(LOG_ERR, "Couldn't set interface address: %m");
return 0;
}
- syslog(LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
+ syslog(LOG_WARNING,
+ "Couldn't set interface address: Address %s already exists",
+ ip_ntoa(o));
}
+ ifaddrs[0] = o;
+ ifaddrs[1] = h;
return 1;
}
@@ -396,31 +990,32 @@ sifaddr(u, o, h, m)
int
cifaddr(u, o, h)
int u;
- u_long o, h;
+ u_int32_t o, h;
{
struct ifaliasreq ifra;
+ ifaddrs[0] = 0;
strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
- if (ioctl(s, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
- syslog(LOG_WARNING, "ioctl(SIOCDIFADDR): %m");
+ if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
+ if (errno != EADDRNOTAVAIL)
+ syslog(LOG_WARNING, "Couldn't delete interface address: %m");
return 0;
}
return 1;
}
-
/*
* sifdefaultroute - assign a default route through the address given.
*/
int
-sifdefaultroute(u, g)
+sifdefaultroute(u, l, g)
int u;
- u_long g;
+ u_int32_t l, g;
{
return dodefaultroute(g, 's');
}
@@ -429,9 +1024,9 @@ sifdefaultroute(u, g)
* cifdefaultroute - delete a default route through the address given.
*/
int
-cifdefaultroute(u, g)
+cifdefaultroute(u, l, g)
int u;
- u_long g;
+ u_int32_t l, g;
{
return dodefaultroute(g, 'c');
}
@@ -439,9 +1034,9 @@ cifdefaultroute(u, g)
/*
* dodefaultroute - talk to a routing socket to add/delete a default route.
*/
-int
+static int
dodefaultroute(g, cmd)
- u_long g;
+ u_int32_t g;
int cmd;
{
int routes;
@@ -453,7 +1048,8 @@ dodefaultroute(g, cmd)
} rtmsg;
if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
- syslog(LOG_ERR, "%cifdefaultroute: opening routing socket: %m", cmd);
+ syslog(LOG_ERR, "Couldn't %s default route: socket: %m",
+ cmd=='s'? "add": "delete");
return 0;
}
@@ -473,12 +1069,14 @@ dodefaultroute(g, cmd)
rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
- syslog(LOG_ERR, "%s default route: %m", cmd=='s'? "add": "delete");
+ syslog(LOG_ERR, "Couldn't %s default route: %m",
+ cmd=='s'? "add": "delete");
close(routes);
return 0;
}
close(routes);
+ default_route_gateway = (cmd == 's')? g: 0;
return 1;
}
@@ -499,10 +1097,9 @@ static int arpmsg_valid;
int
sifproxyarp(unit, hisaddr)
int unit;
- u_long hisaddr;
+ u_int32_t hisaddr;
{
int routes;
- int l;
/*
* Get the hardware address of an interface on the same subnet
@@ -515,7 +1112,7 @@ sifproxyarp(unit, hisaddr)
}
if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
- syslog(LOG_ERR, "sifproxyarp: opening routing socket: %m");
+ syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m");
return 0;
}
@@ -533,13 +1130,14 @@ sifproxyarp(unit, hisaddr)
arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
+ arpmsg.hwa.sdl_len;
if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
- syslog(LOG_ERR, "add proxy arp entry: %m");
+ syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
close(routes);
return 0;
}
close(routes);
arpmsg_valid = 1;
+ proxy_arp_addr = hisaddr;
return 1;
}
@@ -549,7 +1147,7 @@ sifproxyarp(unit, hisaddr)
int
cifproxyarp(unit, hisaddr)
int unit;
- u_long hisaddr;
+ u_int32_t hisaddr;
{
int routes;
@@ -561,17 +1159,18 @@ cifproxyarp(unit, hisaddr)
arpmsg.hdr.rtm_seq = ++rtm_seq;
if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
- syslog(LOG_ERR, "sifproxyarp: opening routing socket: %m");
+ syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m");
return 0;
}
if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
- syslog(LOG_ERR, "delete proxy arp entry: %m");
+ syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m");
close(routes);
return 0;
}
close(routes);
+ proxy_arp_addr = 0;
return 1;
}
@@ -583,7 +1182,7 @@ cifproxyarp(unit, hisaddr)
int
sifproxyarp(unit, hisaddr)
int unit;
- u_long hisaddr;
+ u_int32_t hisaddr;
{
struct arpreq arpreq;
struct {
@@ -608,11 +1207,12 @@ sifproxyarp(unit, hisaddr)
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(s, SIOCSARP, (caddr_t)&arpreq) < 0) {
- syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
+ if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
+ syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
return 0;
}
+ proxy_arp_addr = hisaddr;
return 1;
}
@@ -622,17 +1222,18 @@ sifproxyarp(unit, hisaddr)
int
cifproxyarp(unit, hisaddr)
int unit;
- u_long hisaddr;
+ 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(s, SIOCDARP, (caddr_t)&arpreq) < 0) {
- syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
+ if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
+ syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m");
return 0;
}
+ proxy_arp_addr = 0;
return 1;
}
#endif /* RTM_VERSION */
@@ -644,13 +1245,13 @@ cifproxyarp(unit, hisaddr)
*/
#define MAX_IFS 32
-int
+static int
get_ether_addr(ipaddr, hwaddr)
- u_long ipaddr;
+ u_int32_t ipaddr;
struct sockaddr_dl *hwaddr;
{
struct ifreq *ifr, *ifend, *ifp;
- u_long ina, mask;
+ u_int32_t ina, mask;
struct sockaddr_dl *dla;
struct ifreq ifreq;
struct ifconf ifc;
@@ -658,7 +1259,7 @@ get_ether_addr(ipaddr, hwaddr)
ifc.ifc_len = sizeof(ifs);
ifc.ifc_req = ifs;
- if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
return 0;
}
@@ -668,7 +1269,8 @@ get_ether_addr(ipaddr, hwaddr)
* address on the same subnet as `ipaddr'.
*/
ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
- for (ifr = ifc.ifc_req; ifr < ifend; ) {
+ for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
+ ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
if (ifr->ifr_addr.sa_family == AF_INET) {
ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
@@ -676,7 +1278,7 @@ get_ether_addr(ipaddr, hwaddr)
* Check that the interface is up, and not point-to-point
* or loopback.
*/
- if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0)
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
continue;
if ((ifreq.ifr_flags &
(IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
@@ -685,15 +1287,14 @@ get_ether_addr(ipaddr, hwaddr)
/*
* Get its netmask and check that it's on the right subnet.
*/
- if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0)
+ if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
continue;
- mask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+ mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
if ((ipaddr & mask) != (ina & mask))
continue;
break;
}
- ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
}
if (ifr >= ifend)
@@ -721,23 +1322,142 @@ get_ether_addr(ipaddr, hwaddr)
return 0;
}
+/*
+ * Return user specified netmask, modified by any mask we might determine
+ * for address `addr' (in network byte order).
+ * Here we scan through the system's list of interfaces, looking for
+ * any non-point-to-point interfaces which might appear to be on the same
+ * network as `addr'. If we find any, we OR in their netmask to the
+ * user-specified netmask.
+ */
+u_int32_t
+GetMask(addr)
+ u_int32_t addr;
+{
+ u_int32_t mask, nmask, ina;
+ struct ifreq *ifr, *ifend, ifreq;
+ struct ifconf ifc;
+ struct ifreq ifs[MAX_IFS];
+
+ addr = ntohl(addr);
+ if (IN_CLASSA(addr)) /* determine network mask for address class */
+ nmask = IN_CLASSA_NET;
+ else if (IN_CLASSB(addr))
+ nmask = IN_CLASSB_NET;
+ else
+ nmask = IN_CLASSC_NET;
+ /* class D nets are disallowed by bad_ip_adrs */
+ mask = netmask | htonl(nmask);
+
+ /*
+ * Scan through the system's network interfaces.
+ */
+ ifc.ifc_len = sizeof(ifs);
+ ifc.ifc_req = ifs;
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
+ syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
+ return mask;
+ }
+ ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
+ ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
+ /*
+ * Check the interface's internet address.
+ */
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+ if ((ntohl(ina) & nmask) != (addr & nmask))
+ continue;
+ /*
+ * Check that the interface is up, and not point-to-point or loopback.
+ */
+ strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
+ continue;
+ if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
+ != IFF_UP)
+ continue;
+ /*
+ * Get its netmask and OR it into our mask.
+ */
+ if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
+ continue;
+ mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
+ }
+
+ return mask;
+}
/*
- * ppp_available - check whether the system has any ppp interfaces
- * (in fact we check whether we can do an ioctl on ppp0).
+ * lock - create a lock file for the named lock device
*/
+#define LOCK_PREFIX "/var/spool/lock/LCK.."
+
int
-ppp_available()
+lock(dev)
+ char *dev;
{
- int s, ok;
- struct ifreq ifr;
+ char hdb_lock_buffer[12];
+ int fd, pid, n;
+ char *p;
+
+ if ((p = strrchr(dev, '/')) != NULL)
+ dev = p + 1;
+ lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
+ if (lock_file == NULL)
+ novm("lock file name");
+ strcat(strcpy(lock_file, LOCK_PREFIX), dev);
+
+ while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
+ if (errno == EEXIST
+ && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
+ /* Read the lock file to find out who has the device locked */
+ n = read(fd, hdb_lock_buffer, 11);
+ if (n <= 0) {
+ syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
+ close(fd);
+ } else {
+ hdb_lock_buffer[n] = 0;
+ pid = atoi(hdb_lock_buffer);
+ if (kill(pid, 0) == -1 && errno == ESRCH) {
+ /* pid no longer exists - remove the lock file */
+ if (unlink(lock_file) == 0) {
+ close(fd);
+ syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
+ dev, pid);
+ continue;
+ } else
+ syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
+ dev);
+ } else
+ syslog(LOG_NOTICE, "Device %s is locked by pid %d",
+ dev, pid);
+ }
+ close(fd);
+ } else
+ syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
+ free(lock_file);
+ lock_file = NULL;
+ return -1;
+ }
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- return 1; /* can't tell - maybe we're not root */
+ sprintf(hdb_lock_buffer, "%10d\n", getpid());
+ write(fd, hdb_lock_buffer, 11);
- strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
- ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
- close(s);
+ close(fd);
+ return 0;
+}
- return ok;
+/*
+ * unlock - remove our lockfile
+ */
+void
+unlock()
+{
+ if (lock_file) {
+ unlink(lock_file);
+ free(lock_file);
+ lock_file = NULL;
+ }
}
OpenPOWER on IntegriCloud