home *** CD-ROM | disk | FTP | other *** search
- /*
- * ppp.c - Point-to-Point Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /*
- * TODO:
- * Don't prompt for passwd on /dev/tty (go into server mode).
- * Might want to choose IP addresses from config file based on user id
- * if the server, or based on remote host if tip'd client.
- * Way to set asyncmap.
- * Wait for tty queue to empty before exiting in quit.
- */
-
- /*
- * There are three scenarios:
- * 1. ppp used as daemon started from /etc/rc or perhaps /etc/ttys.
- * a. server
- * b. authentication necessary
- * c. want to use constant local ip addr
- * d. want to use constant remote ip addr, constant ip addr based on
- * authenticated user, or request ip addr
- * 2. ppp used on /dev/tty after remote login.
- * a. server
- * b. no authentication necessary or allowed
- * c. want to use constant local ip addr
- * d. want to use constant remote ip addr, constant ip addr based on
- * authenticated user, or request ip addr
- * 3. ppp used on line after tip'ing out.
- * a. client
- * b. remote end may request authentication
- * c. want to use constant local ip addr or request ip addr
- * d. want to use constant remote ip addr based on tip'd host, or
- * request remote ip addr
- */
-
- #include <stdio.h>
- #include <signal.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <sgtty.h>
- #include <pwd.h>
- #include <syslog.h>
- #include <netdb.h>
- #include <utmp.h>
-
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <sys/callout.h>
-
- #include <net/if.h>
-
- #include "magic.h"
- #include "ppp.h"
- #include "fsm.h"
- #include "lcp.h"
- #include "ipcp.h"
- #include "upap.h"
-
-
- #define PPPHOSTS "/etc/hosts.ppp"
-
- int debug = 0; /* Debug flag */
- int fsm_debug = 0; /* FSM debug flag */
- int lcp_debug = 0; /* LCP debug flag */
- int ipcp_debug = 0; /* IPCP debug flag */
- int upap_debug = 0; /* UPAP debug flag */
-
- char *progname; /* Name of this program */
- char devname[32] = "/dev/tty"; /* Device name */
- char ifname[IFNAMSIZ]; /* Interface name */
- int ifunit; /* Interface unit number */
- char inspeed = 0, outspeed = 0; /* Input/Output speed */
- int fd; /* Device file descriptor */
- int s; /* Socket file descriptor */
- int initdisc; /* Initial TTY discipline */
- struct sgttyb initsgttyb; /* Initial TTY sgttyb */
- int initfdflags; /* Initial file descriptor flags */
- int pid; /* Our pid */
- char user[80]; /* User name */
-
-
- int hup(), intr(), term(), alrm(), io(), incdebug(), nodebug();
- int setdebug(), setpassive(), noopt(), novj(), noupap(), requpap();
- int setspeed(), noaccomp(), noasyncmap(), noipaddr(), nomagicnumber();
- int nomru(), nopcomp();
- void getuserpasswd();
-
-
- /*
- * Valid arguments.
- */
- struct cmd {
- char *cmd_name;
- int (*cmd_func)();
- } cmds[] = {
- "-all", noopt, /* Don't request/allow any options */
- "-ac", noaccomp, /* Disable Address/Control compress */
- "-am", noasyncmap, /* Disable asyncmap negotiation */
- "-d", setdebug, /* Increase debugging level */
- "debug", setdebug, /* Increase debugging level */
- "-ip", noipaddr, /* Disable IP address negotiation */
- "-mn", nomagicnumber, /* Disable magic number negotiation */
- "-mru", nomru, /* Disable mru negotiation */
- "-p", setpassive, /* Set passive mode */
- "-pc", nopcomp, /* Disable protocol field compress */
- "passive", setpassive, /* Set passive mode */
- "+ua", requpap, /* Require UPAP authentication */
- "-ua", noupap, /* Don't allow UPAP authentication */
- "-vj", novj, /* Disable VJ compression */
- #if 0
- "local", setlocalipaddr,
- "remote", setremoteipaddr,
- "test", enabletestline,
- #endif
- NULL
- };
-
-
- /*
- * PPP Data Link Layer "protocol" table.
- * One entry per supported protocol.
- */
- struct protent {
- u_short protocol;
- void (*init)();
- void (*input)();
- void (*protrej)();
- } prottbl[] = {
- { LCP, lcp_init, lcp_input, lcp_protrej },
- { IPCP, ipcp_init, ipcp_input, ipcp_protrej },
- { UPAP, upap_init, upap_input, upap_protrej },
- };
-
-
- char *usage = "usage: %s [-d] [-vj] [mru #]\n\
- \t[local ipaddr] [remote ipaddr]\n\
- \t[ttyname] [speed] [test]\n";
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int pppdisc = PPPDISC;
- int mask, i;
- struct sgttyb sgttyb;
- struct sigvec sv;
- struct cmd *cmdp;
-
- /*
- * Initialize syslog system and magic number package.
- */
- #if BSD >= 43
- openlog("ppp", LOG_PID | LOG_ODELAY, LOG_DAEMON);
- setlogmask(LOG_UPTO(LOG_WARNING));
- #else
- openlog("ppp", LOG_PID);
- #define LOG_UPTO(x) (x)
- #define setlogmask(x) (x)
- #endif
- magic_init();
-
- /*
- * Initialize to the standard option set and then parse the command
- * line arguments.
- */
- for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
- (*prottbl[i].init)(0);
-
- progname = *argv;
- for (argc--, argv++; argc; ) {
- /*
- * First see if it's a command.
- */
- for (cmdp = cmds; cmdp->cmd_name; cmdp++)
- if (!strcmp(*argv, cmdp->cmd_name) &&
- (*cmdp->cmd_func)(&argc, &argv))
- break;
-
- /*
- * Maybe a tty name, speed or IP address?
- */
- if (cmdp->cmd_name == NULL &&
- !setdevname(&argc, &argv) &&
- !setspeed(&argc, &argv) &&
- !setipaddr(&argc, &argv)) {
- fprintf(stderr, usage, progname);
- exit(1);
- }
- }
-
- /*
- * Initialize state.
- */
- if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) {
- perror(devname);
- exit(1);
- }
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- perror("ppp: socket");
- exit(1);
- }
-
- /*
- * Put the tty in raw mode and set the discipline to PPP.
- */
- if (ioctl(fd, TIOCGETP, &initsgttyb) < 0) {
- perror("ppp: ioctl(TIOCGETP)");
- exit(1);
- }
- sgttyb = initsgttyb;
- sgttyb.sg_flags = RAW | ANYP;
- if (inspeed)
- sgttyb.sg_ispeed = inspeed;
- if (outspeed)
- sgttyb.sg_ospeed = outspeed;
- if (ioctl(fd, TIOCSETP, &sgttyb) < 0) {
- perror("ppp: ioctl(TIOCSETP)");
- exit(1);
- }
-
- if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
- perror("ppp: ioctl(TIOCGETD)");
- exit(1);
- }
- if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
- perror("ppp: ioctl(TIOCSETD)");
- exit(1);
- }
-
- /*
- * Find out which interface we were given.
- */
- if (ioctl(fd, TIOCGETD, &ifunit) < 0) {
- perror("ppp: ioctl(TIOCGETD)");
- exit(1);
- }
- sprintf(ifname, "ppp%d", ifunit);
- if (debug)
- printf("Interface %s.\n", ifname);
-
- pid = getpid();
- if (debug)
- printf("Pid %d.\n", pid);
- if (ioctl(fd, TIOCSPGRP, &pid) < 0) {
- perror("ppp: ioctl(TIOCSPGRP)");
- exit(1);
- }
-
- /*
- * Compute mask of all interesting signals and install signal handlers
- * for each. Only one signal handler may be active at a time. Therefore,
- * all other signals should be masked when any handler is executing.
- */
- mask = sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGALRM) |
- sigmask(SIGIO);
- sv.sv_handler = hup; /* Hangup */
- sv.sv_mask = mask;
- sv.sv_flags = 0;
- if (sigvec(SIGHUP, &sv, NULL)) {
- perror("ppp: sigvec(SIGHUP)");
- exit(1);
- }
- sv.sv_handler = intr; /* Interrupt */
- sv.sv_mask = mask;
- sv.sv_flags = 0;
- if (sigvec(SIGINT, &sv, NULL)) {
- perror("ppp: sigvec(SIGINT)");
- exit(1);
- }
- sv.sv_handler = term; /* Terminate */
- sv.sv_mask = mask;
- sv.sv_flags = 0;
- if (sigvec(SIGTERM, &sv, NULL)) {
- perror("ppp: sigvec(SIGTERM)");
- exit(1);
- }
- sv.sv_handler = alrm; /* Timeout */
- sv.sv_mask = mask;
- sv.sv_flags = 0;
- if (sigvec(SIGALRM, &sv, NULL)) {
- perror("ppp: sigvec(SIGALRM)");
- exit(1);
- }
- sv.sv_handler = io; /* Input available */
- sv.sv_mask = mask;
- sv.sv_flags = 0;
- if (sigvec(SIGIO, &sv, NULL)) {
- perror("ppp: sigvec(SIGIO)");
- exit(1);
- }
-
- (void) signal(SIGUSR1, incdebug); /* Increment debug flag */
- (void) signal(SIGUSR2, nodebug); /* Reset debug flag */
-
- /*
- * Record initial device flags, then set device to cause SIGIO
- * signals to be generated.
- */
- if ((initfdflags = fcntl(fd, F_GETFL)) == -1) {
- perror("ppp: fcnt(F_GETFL)");
- exit(1);
- }
- if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) {
- perror("ppp: fcnt(F_SETFL, FNDELAY | FASYNC)");
- exit(1);
- }
-
- /*
- * Block all signals, start opening the connection, and wait for
- * incoming signals (reply, timeout, etc.).
- */
- sigblock(mask); /* Block signals now */
- lcp_lowerup(0); /* XXX Well, sort of... */
- if (lcp_wantoptions[0].passive)
- lcp_passiveopen(0); /* Start protocol in passive mode */
- else
- lcp_activeopen(0); /* Start protocol in active mode */
- for (;;) {
- sigpause(0); /* Wait for next signal */
-
- /* Need to read user/passwd? */
- if (upap[0].us_flags & UPAPF_UPPENDING) {
- sigsetmask(0); /* Allow other signals to occur */
- getuserpasswd(); /* Get user and passwd */
- upap[0].us_flags &= ~UPAPF_UPPENDING;
- upap[0].us_flags |= UPAPF_UPVALID;
- sigsetmask(mask); /* Diallow signals */
- upap_authwithpeer(0);
- }
- }
- }
-
-
- /*
- * quit - Clean up state and exit.
- */
- void quit()
- {
- if (fcntl(fd, F_SETFL, initfdflags) == -1) {
- perror("ppp: fcnt(F_SETFL, fdflags)");
- exit(1);
- }
- if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) {
- perror("ppp: ioctl(TIOCSETP)");
- exit(1);
- }
- if (ioctl(fd, TIOCSETD, &initdisc) < 0) {
- perror("ppp: ioctl(TIOCSETD)");
- exit(1);
- }
- close(fd);
- exit(0);
- }
-
-
- struct callout *callout = NULL; /* Callout list */
- struct timeval schedtime; /* Time last timeout was set */
-
-
- /*
- * timeout - Schedule a timeout.
- *
- * Note that this timeout takes the number of seconds, NOT hz (as in
- * the kernel).
- */
- void timeout(func, arg, time)
- int (*func)();
- caddr_t arg;
- int time;
- {
- struct itimerval itv;
- struct callout *newp, **oldpp;
-
- if (debug > 2)
- printf("Timeout %x:%x in %d seconds.\n", (int) func, (int) arg, time);
-
- /*
- * Allocate timeout.
- */
- if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
- fprintf(stderr, "ppp: Out of memory!\n");
- exit(1);
- }
- newp->c_arg = arg;
- newp->c_func = func;
-
- /*
- * Find correct place to link it in and decrement its time by the
- * amount of time used by preceding timeouts.
- */
- 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;
- if (debug > 2)
- printf("Setting itimer for %d seconds.\n", itv.it_value.tv_sec);
- if (setitimer(ITIMER_REAL, &itv, NULL)) {
- perror("ppp: setitimer(ITIMER_REAL)");
- exit(1);
- }
- if (gettimeofday(&schedtime, NULL)) {
- perror("ppp: gettimeofday");
- exit(1);
- }
- }
- }
-
-
- /*
- * untimeout - Unschedule a timeout.
- */
- void untimeout(func, arg)
- int (*func)();
- caddr_t arg;
- {
-
- struct itimerval itv;
- struct callout **copp, *freep;
- int reschedule = 0;
-
- if (debug > 2)
- printf("Untimeout %x:%x.\n", (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;
-
- /*
- * Find first matching timeout. Add its time to the next timeouts
- * time.
- */
- for (copp = &callout; *copp; copp = &(*copp)->c_next)
- if ((*copp)->c_func == func &&
- (*copp)->c_arg == arg) {
- freep = *copp;
- *copp = freep->c_next;
- if (*copp)
- (*copp)->c_time += freep->c_time;
- free(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;
- if (debug > 2)
- printf("Setting itimer for %d seconds.\n", itv.it_value.tv_sec);
- if (setitimer(ITIMER_REAL, &itv, NULL)) {
- perror("ppp: setitimer(ITIMER_REAL)");
- exit(1);
- }
- if (gettimeofday(&schedtime, NULL)) {
- perror("ppp: gettimeofday");
- exit(1);
- }
- }
- }
-
-
- /*
- * adjtimeout - Decrement the first timeout by the amount of time since
- * it was scheduled.
- */
- void adjtimeout()
- {
- 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)) {
- perror("ppp: gettimeofday");
- exit(1);
- }
- timediff = tv.tv_sec - schedtime.tv_sec;
- if (timediff < 0 ||
- timediff > callout->c_time + 1)
- return;
-
- callout->c_time -= timediff; /* OK, Adjust time */
- }
-
-
- /*
- * output - Output PPP packet.
- */
- void output(unit, p, len)
- int unit;
- u_char *p;
- int len;
- {
- if (unit != 0) {
- fprintf(stderr, "ppp: output: unit != 0!\n");
- abort();
- }
- if (write(fd, p, len) < 0) {
- perror("ppp: write");
- exit(1);
- }
- free(p);
- }
-
-
- /*
- * hup - Catch SIGHUP signal.
- *
- * Indicates that the physical layer has been disconnected.
- */
- hup()
- {
- if (debug > 1)
- printf("Hangup\n");
- adjtimeout(); /* Adjust timeouts */
- lcp_lowerdown(0); /* Reset connection */
- }
-
-
- /*
- * term - Catch SIGTERM signal.
- *
- * Indicates that we should initiate a graceful disconnect and exit.
- */
- term()
- {
- if (debug > 1)
- printf("Terminate\n");
- adjtimeout(); /* Adjust timeouts */
- lcp_close(0); /* Close connection */
- }
-
-
- /*
- * intr - Catch SIGINT signal (DEL/^C).
- *
- * Indicates that we should initiate a graceful disconnect and exit.
- */
- intr()
- {
- if (debug > 1)
- printf("Interrupt\n");
- adjtimeout(); /* Adjust timeouts */
- lcp_close(0); /* Close connection */
- }
-
-
- /*
- * alrm - Catch SIGALRM signal.
- *
- * Indicates a timeout.
- */
- alrm()
- {
- struct itimerval itv;
- struct callout *freep;
-
- if (debug > 1)
- printf("Alarm\n");
-
- /*
- * Call and free first scheduled timeout and any that were scheduled
- * for the same time.
- */
- while (callout) {
- freep = callout; /* Remove entry before calling */
- callout = freep->c_next;
- (*freep->c_func)(freep->c_arg);
- free(freep);
- if (callout->c_time)
- break;
- }
-
- /*
- * Set a new itimer if there are more timeouts scheduled.
- */
- if (callout) {
- itv.it_interval.tv_sec = itv.it_interval.tv_usec =
- itv.it_value.tv_usec = 0;
- itv.it_value.tv_sec = callout->c_time;
- if (debug > 2)
- printf("Setting itimer for %d seconds.\n", itv.it_value.tv_sec);
- if (setitimer(ITIMER_REAL, &itv, NULL)) {
- perror("ppp: setitimer(ITIMER_REAL)");
- exit(1);
- }
- if (gettimeofday(&schedtime, NULL)) {
- perror("ppp: gettimeofday");
- exit(1);
- }
- }
- }
-
-
- /*
- * io - Catch SIGIO signal.
- *
- * Indicates that incoming data is available.
- */
- io()
- {
- int len, i;
- u_char *p;
- u_short protocol;
-
- if (debug > 1)
- printf("IO\n");
- adjtimeout(); /* Adjust timeouts */
-
- for (;;) { /* Read all available packets */
- p = (u_char *) malloc(MTU + DLLHEADERLEN);
- if ((len = read(fd, p, MTU + DLLHEADERLEN)) < 0) {
- if (errno == EWOULDBLOCK) {
- if (debug > 2)
- perror("ppp: read(fd)");
- return;
- }
- else {
- perror("ppp: read(fd)");
- exit(1);
- }
- }
- else if (len == 0) {
- fprintf(stderr, "ppp: End of file on fd!\n");
- exit(1);
- }
-
- if (len < DLLHEADERLEN) {
- if (debug)
- fprintf(stderr, "ppp: input: Received short packet.\n");
- 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 != OPEN) {
- free(p);
- 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)) {
- if (debug)
- fprintf(stderr,
- "ppp: input: Unknown protocol (%x) received!\n",
- protocol);
- p -= DLLHEADERLEN;
- len += DLLHEADERLEN;
- lcp_sprotrej(0, p, len);
- }
- }
- }
-
-
- /*
- * 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;
- }
- if (debug)
- fprintf(stderr,
- "ppp: demuxprotrej: Unrecognized Protocol-Reject!\n");
- }
-
-
- /*
- * incdebug - Catch SIGUSR1 signal.
- *
- * Increment debug flag.
- */
- incdebug()
- {
- debug++;
- }
-
-
- /*
- * nodebug - Catch SIGUSR2 signal.
- *
- * Turn off debugging.
- */
- nodebug()
- {
- debug = 0;
- }
-
-
- /*
- * setdebug - Set debug (command line argument).
- */
- int setdebug(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- debug++;
- fsm_debug++;
- lcp_debug++;
- ipcp_debug++;
- upap_debug++;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * noopt - Disable all options.
- */
- int noopt(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- bzero(&lcp_wantoptions[0], sizeof (struct lcp_options));
- bzero(&lcp_allowoptions[0], sizeof (struct lcp_options));
- bzero(&ipcp_wantoptions[0], sizeof (struct ipcp_options));
- bzero(&ipcp_allowoptions[0], sizeof (struct ipcp_options));
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * noaccomp - Disable Address/Control field compression negotiation.
- */
- int noaccomp(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_wantoptions[0].neg_accompression = 0;
- lcp_allowoptions[0].neg_accompression = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * noasyncmap - Disable async map negotiation.
- */
- int noasyncmap(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_wantoptions[0].neg_asyncmap = 0;
- lcp_allowoptions[0].neg_asyncmap = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * noipaddr - Disable IP address negotiation.
- */
- int noipaddr(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- ipcp_wantoptions[0].neg_addrs = 0;
- ipcp_allowoptions[0].neg_addrs = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * nomagicnumber - Disable magic number negotiation.
- */
- int nomagicnumber(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_wantoptions[0].neg_magicnumber = 0;
- lcp_allowoptions[0].neg_magicnumber = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * nomru - Disable mru negotiation.
- */
- int nomru(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_wantoptions[0].neg_mru = 0;
- lcp_allowoptions[0].neg_mru = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * nopcomp - Disable Protocol field compression negotiation.
- */
- int nopcomp(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_wantoptions[0].neg_pcompression = 0;
- lcp_allowoptions[0].neg_pcompression = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * setpassive - Set passive mode.
- */
- int setpassive(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_wantoptions[0].passive = 1;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * noupap - Disable UPAP authentication.
- */
- int noupap(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_allowoptions[0].neg_upap = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * requpap - Require UPAP authentication.
- */
- int requpap(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- lcp_wantoptions[0].neg_upap = 1;
- lcp_allowoptions[0].neg_upap = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * novj - Disable Van Jacobson style IP header compression.
- */
- int novj(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- ipcp_wantoptions[0].neg_vj = 0;
- ipcp_allowoptions[0].neg_vj = 0;
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * 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 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 EXTA
- { 19200, EXTA },
- #endif
- #ifdef EXTB
- { 38400, EXTB },
- #endif
- { 0, 0 }
- };
-
- /*
- * setspeed - Set the speed.
- */
- int setspeed(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- int speed;
- struct speed *speedp;
-
- speed = atoi(**argvp);
- for (speedp = speeds; speedp->speed_int; speedp++)
- if (speed == speedp->speed_int) {
- inspeed = speedp->speed_val;
- --*argcp, ++*argvp;
- return (1);
- }
- return (0);
- }
-
-
- /*
- * setdevname - Set the device name.
- */
- int setdevname(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- char dev[32];
- char *cp = **argvp;
- struct stat statbuf;
- char *tty, *ttyname();
-
- if (strncmp("/dev/", cp, sizeof ("/dev/") - 1)) {
- (void) sprintf(dev, "/dev/%s", cp);
- cp = dev;
- }
-
- /*
- * Check if there is a device by this name.
- */
- if (stat(cp, &statbuf) < 0) {
- if (errno == ENOENT)
- return (0);
- perror(cp);
- exit(1);
- }
-
- strcpy(devname, cp);
- --*argcp, ++*argvp;
-
- /*
- * If we haven't already decided to require authentication,
- * or we are running ppp on the control terminal, then we can
- * allow authentication to be requested.
- */
- tty = ttyname(fileno(stdin));
- if (lcp_wantoptions[0].neg_upap == 0 &&
- strcmp(devname, "/dev/tty") &&
- strcmp(devname, tty)) {
- lcp_wantoptions[0].neg_upap = 0;
- lcp_allowoptions[0].neg_upap = 1;
- }
- return (1);
- }
-
-
- /*
- * setipaddr - Set the speed.
- */
- int setipaddr(argcp, argvp)
- int *argcp;
- char ***argvp;
- {
- u_long local, remote;
- struct hostent *hp;
- char *colon, *index();
-
- /*
- * IP address pair separated by ":".
- */
- if ((colon = index(**argvp, ':')) == NULL)
- return (0);
-
- /*
- * If colon first character, then no local addr.
- */
- if (colon == **argvp) {
- local = 0l;
- ++colon;
- }
- else {
- *colon++ = '\0';
- if ((local = inet_addr(**argvp)) == -1) {
- if ((hp = gethostbyname(**argvp)) == NULL) {
- fprintf(stderr, "unknown host: %s\n", **argvp);
- goto ret;
- }
- bcopy(hp->h_addr, (char *) &local, hp->h_length);
- }
- }
-
- /*
- * If colon last character, then no remote addr.
- */
- if (*colon == '\0')
- remote = 0l;
- else {
- if ((remote = inet_addr(colon)) == -1) {
- if ((hp = gethostbyname(colon)) == NULL) {
- fprintf(stderr, "unknown host: %s\n", colon);
- goto ret;
- }
- bcopy(hp->h_addr, (char *) &remote, hp->h_length);
- }
- }
-
- ipcp_wantoptions[0].neg_addrs = 1;
- ipcp_wantoptions[0].ouraddr = local;
- ipcp_wantoptions[0].hisaddr = remote;
-
- ret:
- --*argcp, ++*argvp;
- return (1);
- }
-
-
- /*
- * getuserpasswd - Get the user name and passwd.
- */
- void getuserpasswd()
- {
- struct passwd *pw, *getpwuid();
- char *getlogin(), *getpass();
-
- /*
- * Prompt for user name with a default value. Default is
- * the last value if any, or the login name or the user name.
- */
- if (upap[0].us_user == NULL &&
- (upap[0].us_user = getlogin()) == NULL &&
- (pw = getpwuid(getuid())) != NULL)
- upap[0].us_user = pw->pw_name;
-
- printf("Login (%s): ", upap[0].us_user);
- fgets(user, sizeof (user) - 1, stdin);
- user[strlen(user) - 1] = '\0';
- if (user[0] != '\0') /* Choosing the default? */
- upap[0].us_user = user;
- upap[0].us_userlen = strlen(upap[0].us_user);
-
- upap[0].us_passwd = getpass("Password: ");
- upap[0].us_passwdlen = strlen(upap[0].us_passwd);
- }
-
-
- /*
- * login - Check the user name and passwd and login the user.
- *
- * returns:
- * UPAP_AUTHNAK: Login failed.
- * UPAP_AUTHACK: Login succeeded.
- * In either case, msg points to an appropriate message.
- */
- u_char login(user, userlen, passwd, passwdlen, msg, msglen)
- char *user;
- int userlen;
- char *passwd;
- int passwdlen;
- char **msg;
- int *msglen;
- {
- struct passwd *pw;
- char *epasswd, *crypt();
- static int attempts = 0;
- char *tty, *rindex();
-
- *(user + userlen) = '\0';
- *(passwd + passwdlen) = '\0';
-
- if ((pw = getpwnam(user)) == NULL) {
- *msg = "Login incorrect";
- *msglen = strlen(*msg);
- return (UPAP_AUTHNAK);
- }
-
- /*
- * XXX If no passwd, let them login without one.
- */
- if (pw->pw_passwd == '\0') {
- *msg = "Login ok";
- *msglen = strlen(*msg);
- return (UPAP_AUTHACK);
- }
-
- epasswd = crypt(passwd, pw->pw_passwd);
- if (strcmp(epasswd, pw->pw_passwd)) {
- *msg = "Login incorrect";
- *msglen = strlen(*msg);
-
- /*
- * Frustrate passwd stealer programs.
- * Allow 10 tries, but start backing off after 3 (stolen from login).
- * On 10'th, drop the connection.
- */
- if (attempts++ >= 10) {
- syslog(LOG_NOTICE, "%d LOGIN FAILURES ON %s, %s",
- attempts, devname, user);
- lcp_close(0); /* Drop DTR? */
- }
- if (attempts > 3)
- sleep((u_int) (attempts - 3) * 5);
- return (UPAP_AUTHNAK);
- }
-
- attempts = 0; /* Reset count */
- *msg = "Login ok";
- *msglen = strlen(*msg);
-
- tty = rindex(devname, '/');
- if (tty == NULL)
- tty = devname;
- else
- tty++;
- logwtmp(tty, user, ""); /* Add wtmp login entry */
-
- return (UPAP_AUTHACK);
- }
-
-
- /*
- * logout - Logout the user.
- */
- void logout()
- {
- char *tty;
-
- tty = rindex(devname, '/');
- if (tty == NULL)
- tty = devname;
- else
- tty++;
- logwtmp(tty, "", ""); /* Add wtmp logout entry */
- }
-
-
- /*
- * getuseropt - Get the options from /etc/hosts.ppp for this user.
- */
- int getuseropt(user)
- char *user;
- {
- char buf[1024], *s;
- FILE *fp;
- int rc = 0;
-
- if ((fp = fopen(PPPHOSTS, "r")) == NULL)
- return (0);;
-
- /*
- * Loop till we find an entry for this user.
- */
- for (;;) {
- if (fgets(buf, sizeof (buf), fp)) {
- if (feof(fp))
- break;
- else {
- perror("fgets");
- exit(1);
- }
- }
- if ((s = index(buf, ' ')) == NULL)
- continue;
- *s++ = '\0';
- if (!strcmp(user, buf)) {
- rc = 1;
- break;
- }
- }
- fclose(fp);
- return (rc);
- }
-