diff options
Diffstat (limited to 'libexec/pppd/main.c')
-rw-r--r-- | libexec/pppd/main.c | 2701 |
1 files changed, 825 insertions, 1876 deletions
diff --git a/libexec/pppd/main.c b/libexec/pppd/main.c index 557bc555e273..828d20bf818f 100644 --- a/libexec/pppd/main.c +++ b/libexec/pppd/main.c @@ -17,64 +17,45 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -/* - * There are three scenarios: - * 1. pppd 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. pppd 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. pppd 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 - */ - -#ifdef __386BSD__ -#include <stdlib.h> +#ifndef lint +static char rcsid[] = "$Id: main.c,v 1.4 1994/03/30 09:31:35 jkh Exp $"; #endif +#define SETSID + #include <stdio.h> #include <signal.h> #include <errno.h> #include <fcntl.h> -#include <pwd.h> #include <syslog.h> #include <netdb.h> #include <utmp.h> -#ifdef sparc -#include <alloca.h> +/* + * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless + * /etc/ppp/options exists. + */ +#ifndef REQ_SYSOPTIONS +#define REQ_SYSOPTIONS 0 #endif #ifdef STREAMS -#include <sys/stream.h> -#include <sys/stropts.h> -#include <sys/termios.h> -#else +#undef SGTTY +#endif + #ifdef SGTTY #include <sgtty.h> #else +#ifndef sun #include <sys/ioctl.h> -#include <termios.h> #endif +#include <termios.h> #endif #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> #include <sys/time.h> #include "callout.h" @@ -82,19 +63,13 @@ #include <net/if.h> #include <net/if_ppp.h> -#ifdef STREAMS -#include "ppp_str.h" -#endif - -#define DEVNAME_SIZE 128 /* Buffer size for /dev filenames */ - #include <string.h> #ifndef BSD #define BSD 43 #endif /*BSD*/ -#include <net/ppp.h> +#include "ppp.h" #include "magic.h" #include "fsm.h" #include "lcp.h" @@ -116,55 +91,63 @@ #endif /*FALSE*/ #ifdef PIDPATH -static char *pidpath = PIDPATH; /* filename in which pid will be */ - /* stored */ +static char *pidpath = PIDPATH; /* filename in which pid will be stored */ #else static char *pidpath = _PATH_PIDFILE; #endif /* PIDFILE */ -static char uinfopath[DEVNAME_SIZE]; - /* interface vars */ - char ifname[IFNAMSIZ]; /* Interface name */ -int ifunit; /* Interface unit number */ +int ifunit; /* Interface unit number */ char *progname; /* Name of this program */ -char hostname[MAX_HOSTNAME_LEN]; /* hostname */ -u_char hostname_len; /* hostname length */ - -static pid_t pid; /* Our pid */ -static pid_t pgrpid; /* Process Group ID */ -static char pidfilename[DEVNAME_SIZE]; - -static char devname[DEVNAME_SIZE] = "/dev/tty"; /* Device name */ -static int default_device = TRUE; /* use default device (stdin/out) */ -int fd; /* Device file descriptor */ -int s; /* Socket file descriptor */ -static int initdisc; /* Initial TTY discipline */ -#ifndef STREAMS +char hostname[MAXNAMELEN]; /* Our hostname */ +char our_name[MAXNAMELEN]; +char remote_name[MAXNAMELEN]; + +static pid_t pid; /* Our pid */ +static pid_t pgrpid; /* Process Group ID */ +static char pidfilename[MAXPATHLEN]; + +char devname[MAXPATHLEN] = "/dev/tty"; /* Device name */ +int default_device = TRUE; /* use default device (stdin/out) */ + +int fd; /* Device file descriptor */ +int s; /* Socket file descriptor */ + #ifdef SGTTY static struct sgttyb initsgttyb; /* Initial TTY sgttyb */ #else -static struct termios inittermios; /* Initial TTY TIOCGETA */ -#endif +static struct termios inittermios; /* Initial TTY termios */ #endif -static int initfdflags; /* Initial file descriptor flags */ +static int initfdflags = -1; /* Initial file descriptor flags */ + +static int restore_term; /* 1 => we've munged the terminal */ u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */ static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* buffer for incoming packet */ +int hungup; /* terminal has been hung up */ + /* configured variables */ int debug = 0; /* Debug flag */ -static char user[80]; /* User name */ -static char passwd[80]; /* password */ -static char *connector = NULL; /* "connect" command */ -static int inspeed = 0; /* Input/Output speed */ -static u_long netmask = 0; /* netmask to use on ppp interface */ -static int crtscts = 0; /* use h/w flow control */ -static int nodetach = 0; /* don't fork */ +char user[MAXNAMELEN]; /* username for PAP */ +char passwd[MAXSECRETLEN]; /* password for PAP */ +char *connector = NULL; /* "connect" command */ +int inspeed = 0; /* Input/Output speed */ +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 */ + /* prototypes */ static void hup __ARGS((int, int, struct sigcontext *, char *)); @@ -172,761 +155,657 @@ static void intr __ARGS((int, int, struct sigcontext *, char *)); static void term __ARGS((int, int, struct sigcontext *, char *)); static void alrm __ARGS((int, int, struct sigcontext *, char *)); static void io __ARGS((int, int, struct sigcontext *, char *)); -static void incdebug __ARGS((int, int, struct sigcontext *, char *)); -static void nodebug __ARGS((int, int, struct sigcontext *, char *)); -static void getuserpasswd __ARGS((void)); - -static int setdebug __ARGS((int *, char ***)); -static int setpassive __ARGS((int *, char ***)); -static int noopt __ARGS((int *, char ***)); -static int setnovj __ARGS((int *, char ***)); -static int noupap __ARGS((int *, char ***)); -static int requpap __ARGS((int *, char ***)); -static int nochap __ARGS((int *, char ***)); -static int reqchap __ARGS((int *, char ***)); -static int setspeed __ARGS((int *, char ***)); -static int noaccomp __ARGS((int *, char ***)); -static int noasyncmap __ARGS((int *, char ***)); -static int noipaddr __ARGS((int *, char ***)); -static int nomagicnumber __ARGS((int *, char ***)); -static int setasyncmap __ARGS((int *, char ***)); -static int setvjmode __ARGS((int *, char ***)); -static int setmru __ARGS((int *, char ***)); -static int nomru __ARGS((int *, char ***)); -static int nopcomp __ARGS((int *, char ***)); -static int setconnector __ARGS((int *, char ***)); -static int setdomain __ARGS((int *, char ***)); -static int setnetmask __ARGS((int *, char ***)); -static int setcrtscts __ARGS((int *, char ***)); -static int setnodetach __ARGS((int *, char ***)); -static void cleanup __ARGS((int, caddr_t)); +static void incdebug __ARGS((int)); +static void nodebug __ARGS((int)); +void establish_ppp __ARGS((void)); + +void cleanup __ARGS((int, caddr_t)); +void die __ARGS((int)); +void dumpbuffer __ARGS((unsigned char *, int, int)); #ifdef STREAMS -static void str_restore __ARGS((void)); extern char *ttyname __ARGS((int)); -#define MAXMODULES 10 /* max number of module names that we can save */ -static struct modlist { - char modname[FMNAMESZ+1]; -} str_modules[MAXMODULES]; -static int str_module_count = 0; #endif - -/* - * Valid arguments. - */ -static 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 */ - "-as", setasyncmap, /* set the desired async map */ - "-d", setdebug, /* Increase debugging level */ - "-detach", setnodetach, /* don't fork */ - "-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 */ - "+ua", requpap, /* Require UPAP authentication */ - "-ua", noupap, /* Don't allow UPAP authentication */ - "+chap", reqchap, /* Require CHAP authentication */ - "-chap", nochap, /* Don't allow CHAP authentication */ - "-vj", setnovj, /* disable VJ compression */ - "asyncmap", setasyncmap, /* set the desired async map */ - "connect", setconnector, /* A program to set up a connection */ - "crtscts", setcrtscts, /* set h/w flow control */ - "debug", setdebug, /* Increase debugging level */ - "domain", setdomain, /* Add given domain name to hostname*/ - "mru", setmru, /* Set MRU value for negotiation */ - "netmask", setnetmask, /* set netmask */ - "passive", setpassive, /* Set passive mode */ - "vjmode", setvjmode, /* set VJ compression mode */ - NULL - }; - +extern char *getlogin __ARGS((void)); /* * PPP Data Link Layer "protocol" table. * One entry per supported protocol. */ static struct protent { - u_short protocol; - void (*init)(); - void (*input)(); - void (*protrej)(); + 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 }, - { CHAP, ChapInit, ChapInput, ChapProtocolReject }, + { LCP, lcp_init, lcp_input, lcp_protrej }, + { IPCP, ipcp_init, ipcp_input, ipcp_protrej }, + { UPAP, upap_init, upap_input, upap_protrej }, + { CHAP, ChapInit, ChapInput, ChapProtocolReject }, }; -static char *usage = "pppd version %s patch level %d\n\ -Usage: %s [ arguments ], where arguments are:\n\ - -all Don't request/allow any options\n\ - -ac Disable Address/Control compression\n\ - -am Disable asyncmap negotiation\n\ - -as <n> Set the desired async map to hex <n>\n\ - -d Increase debugging level\n\ - -detach Don't fork to background\n\ - -ip Disable IP address negotiation\n\ - -mn Disable magic number negotiation\n\ - -mru Disable mru negotiation\n\ - -p Set passive mode\n\ - -pc Disable protocol field compression\n\ - +ua <p> Require UPAP authentication and use file <p> for\n\ - remote login data\n\ - -ua Don't allow UPAP authentication\n\ - +chap Require CHAP authentication\n\ - -chap Don't allow CHAP authentication\n\ - -vj disable VJ compression\n\ - connect <p> Invoke shell command <p> to set up the serial line\n\ - crtscts Use hardware RTS/CTS flow control\n\ - debug Increase debugging level\n\ - domain <d> Append domain name <d> to hostname for authentication\n\ - mru <n> Set MRU value to <n> for negotiation\n\ - netmask <n> Set interface netmask to <n>\n\ - passive Set passive mode\n\ - vjmode <m> VJ compression mode {old, rfc1172, rfc1132 (default)}\n\ - <device> Communicate over the named device\n\ - <speed> Set the baud rate to <speed>\n\ - <loc>:<rem> Set the local and/or remote interface IP\n\ - addresses. Either one may be omitted.\n"; - - main(argc, argv) - int argc; - char *argv[]; + int argc; + char *argv[]; { - int mask, i; - struct sigvec sv; - struct cmd *cmdp; - FILE *pidfile; -#ifndef STREAMS - int pppdisc = PPPDISC; -#endif + int mask, i; + struct sigvec sv; + struct cmd *cmdp; + FILE *pidfile; + char *p; - /* - * Initialize syslog system and magic number package. - */ + /* + * Initialize syslog system and magic number package. + */ #if BSD >= 43 || defined(sun) - openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); - setlogmask(LOG_UPTO(LOG_INFO)); + openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); + setlogmask(LOG_UPTO(LOG_INFO)); #else - openlog("pppd", LOG_PID); + openlog("pppd", LOG_PID); #define LOG_UPTO(x) (x) #define setlogmask(x) (x) #endif #ifdef STREAMS - if (ttyname(fileno(stdin))) - strcpy(devname, ttyname(fileno(stdin))); + p = ttyname(fileno(stdin)); + if (p) + strcpy(devname, p); #endif - magic_init(); - - if (gethostname(hostname, MAX_HOSTNAME_LEN) < 0 ) { - syslog(LOG_ERR, "couldn't get hostname: %m"); - exit(1); - } - - /* - * 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, VERSION, PATCHLEVEL, progname); - exit(1); + magic_init(); + + if (gethostname(hostname, MAXNAMELEN) < 0 ) { + syslog(LOG_ERR, "couldn't get hostname: %m"); + die(1); } - } + hostname[MAXNAMELEN-1] = 0; - syslog(LOG_INFO, "Starting pppd %s patch level %d", - VERSION, PATCHLEVEL); + pid = getpid(); - /* - * Initialize state. - */ + if (!ppp_available()) { + fprintf(stderr, "Sorry - PPP is not available on this system\n"); + exit(1); + } + /* + * Initialize to the standard option set, then parse, in order, + * the system options file, the user's options file, and the command + * line arguments. + */ + for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) + (*prottbl[i].init)(0); + + progname = *argv; + + if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS) || + !options_from_user() || + !parse_args(argc-1, argv+1)) + die(1); + check_auth_options(); + setipdefault(); + + p = getlogin(); + if (p == NULL) + p = "(unknown)"; + syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d", + VERSION, PATCHLEVEL, p, getuid()); -#define SETSID #ifdef SETSID - if (default_device) { - /* No device name was specified... inherit the old controlling - terminal */ - - if ((pgrpid = getpgrp(0)) < 0) { - syslog(LOG_ERR, "getpgrp(0): %m"); - exit(1); + /* + * 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); + } } - if (pgrpid != pid) - syslog(LOG_WARNING, "warning... not a process group leader"); - } - else /*default_device*/ - { - /* become session leader... */ - - if (!nodetach) { - /* fork so we're not a process group leader */ - if (pid = fork()) { - exit(0); - } - } -#ifdef xxx - else - /* bag controlling terminal */ - if (ioctl(0, TIOCNOTTY) < 0) { - syslog(LOG_ERR, "ioctl(TIOCNOTTY): %m"); - exit(1); - } #endif - /* create new session */ - if ((pgrpid = setsid()) < 0) { - syslog(LOG_ERR, "setsid(): %m"); - exit(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); + } + + /* + * 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. + */ + sigemptyset(&mask); + sigaddset(&mask, SIGHUP); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGALRM); + sigaddset(&mask, SIGIO); +#ifdef STREAMS + sigaddset(&mask, SIGPOLL); #endif - /* open i/o device */ - if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) { - syslog(LOG_ERR, "open(%s): %m", devname); - exit(1); - } - - /* drop dtr to hang up incase modem is off hook */ - if (!default_device) { - setdtr(fd, FALSE); - sleep(1); - setdtr(fd, TRUE); - } - - /* set device to be controlling tty */ - if (ioctl(fd, TIOCSCTTY) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSCTTY): %m"); - exit(1); - } - - /* run connection script */ - if (connector) { - syslog(LOG_NOTICE, "Connecting with <%s>", connector); - /* set line speed */ - set_up_tty(fd, 0); - if (set_up_connection(connector, fd, fd) < 0) { - syslog(LOG_ERR, "could not set up connection"); - setdtr(fd, FALSE); - exit(1); +#define SIGNAL(s, handler) { \ + sv.sv_handler = handler; \ + if (sigvec(s, &sv, NULL) < 0) { \ + syslog(LOG_ERR, "sigvec(%d): %m", s); \ + die(1); \ + } \ } - syslog(LOG_NOTICE, "Connected..."); - } - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "socket : %m"); - exit(1); - } - - /* if we exit, then try and restore the stream */ -#ifdef sun - on_exit(cleanup, NULL); + + sv.sv_mask = mask; + sv.sv_flags = 0; + SIGNAL(SIGHUP, hup); /* Hangup */ + SIGNAL(SIGINT, intr); /* Interrupt */ + SIGNAL(SIGTERM, term); /* Terminate */ + SIGNAL(SIGALRM, alrm); /* Timeout */ + SIGNAL(SIGIO, io); /* Input available */ +#ifdef STREAMS + SIGNAL(SIGPOLL, io); /* Input available */ #endif - + + signal(SIGUSR1, incdebug); /* Increment debug flag */ + signal(SIGUSR2, nodebug); /* Reset debug flag */ + + /* + * Block SIGIOs and SIGPOLLs for now + */ + sigemptyset(&mask); + sigaddset(&mask, SIGIO); #ifdef STREAMS - /* go through and save the name of all the modules, then pop em */ - while(1) { - if(!ioctl(fd, I_LOOK, str_modules[str_module_count].modname)) - MAINDEBUG((LOG_DEBUG, "popped stream module : %s", - str_modules[str_module_count].modname)) - if(!ioctl(fd, I_POP, 0)) - str_module_count++; - else - break; - } - - /* set line speed */ - set_up_tty(fd, 1); - - syslog(LOG_ERR, "about to push modules..."); - - /* now push the async/fcs module */ - if(ioctl(fd, I_PUSH, "pppasync") < 0) { - syslog(LOG_ERR, "ioctl(I_PUSH, ppp_async): %m"); - exit(1); - } - /* finally, push the ppp_if module that actually handles the */ - /* network interface */ - if(ioctl(fd, I_PUSH, "pppif") < 0) { - syslog(LOG_ERR, "ioctl(I_PUSH, ppp_if): %m"); - exit(1); - } - if(ioctl(fd, I_SETSIG, S_INPUT) < 0) { - syslog(LOG_ERR, "ioctl(I_SETSIG, S_INPUT): %m"); - exit(1); - } - /* read mode, message non-discard mode */ - if(ioctl(fd, I_SRDOPT, RMSGN) < 0) { - syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m"); - exit(1); - } - /* Flush any waiting messages, or we'll never get SIGPOLL */ - if(ioctl(fd, I_FLUSH, FLUSHRW) < 0) { - syslog(LOG_ERR, "ioctl(I_FLUSH, FLUSHRW): %m"); - exit(1); - } - /* - * Find out which interface we were given. - * (ppp_if handles this ioctl) - */ - if (ioctl(fd, SIOCGETU, &ifunit) < 0) { - syslog(LOG_ERR, "ioctl(SIOCGETU): %m"); - exit(1); - } - - /* if debug, set debug flags in driver */ - { - int flags = debug ? 0x3 : 0; -syslog(LOG_INFO, "debug 0x%x, flags 0x%x", debug, flags); - if (ioctl(fd, SIOCSIFDEBUG, &flags) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m"); - } - } - - syslog(LOG_ERR, "done pushing modules, ifunit %d", ifunit); -#else - /* set line speed */ - set_up_tty(fd, 1); - - if (ioctl(fd, TIOCGETD, &initdisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCGETD): %m"); - exit(1); - } - if (ioctl(fd, TIOCSETD, &pppdisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - exit(1); - } - - /* - * Find out which interface we were given. - */ - if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); - exit(1); - } + sigaddset(&mask, SIGPOLL); #endif + sigprocmask(SIG_BLOCK, &mask, NULL); + + /* + * Open the serial device and set it up to be the ppp interface. + */ + if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) { + syslog(LOG_ERR, "open(%s): %m", devname); + die(1); + } + hungup = 0; - syslog(LOG_NOTICE, "Using interface ppp%d", ifunit); - (void) sprintf(ifname, "ppp%d", ifunit); - pid = getpid(); + /* set device to be controlling tty */ + if (!default_device && ioctl(fd, TIOCSCTTY) < 0) { + syslog(LOG_ERR, "ioctl(TIOCSCTTY): %m"); + die(1); + } - (void) sprintf(pidfilename, "%s/%s.pid", pidpath, ifname); + /* set line speed, flow control, etc. */ + set_up_tty(fd); - /* write pid to file */ + /* run connection script */ + if (connector) { + syslog(LOG_INFO, "Connecting with <%s>", connector); - if ((pidfile = fopen(pidfilename, "w")) != NULL) { - fprintf(pidfile, "%d\n", pid); - (void) fclose(pidfile); - } + /* drop dtr to hang up in case modem is off hook */ + if (!default_device && modem) { + setdtr(fd, FALSE); + sleep(1); + setdtr(fd, TRUE); + } - hostname_len = (u_char) strlen(hostname); + if (set_up_connection(connector, fd, fd) < 0) { + syslog(LOG_ERR, "could not set up connection"); + setdtr(fd, FALSE); + die(1); + } - MAINDEBUG((LOG_DEBUG, "hostname = %s", hostname)) - -#ifdef SETSID - if (default_device) { - int id = tcgetpgrp(fd); - if (id != pgrpid) { - syslog(LOG_WARNING, - "warning: pppd is not the leader of a forground process group"); + syslog(LOG_INFO, "Connected..."); + sleep(1); /* give it time to set up its terminal */ } - } - else - if (tcsetpgrp(fd, pgrpid) < 0) { - syslog(LOG_ERR, "tcsetpgrp(): %m"); - exit(1); + + /* set up the serial device as a ppp interface */ + establish_ppp(); + + syslog(LOG_INFO, "Using interface ppp%d", ifunit); + (void) sprintf(ifname, "ppp%d", ifunit); + + /* 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 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"); + } + } else { + if (tcsetpgrp(fd, pgrpid) < 0) { + syslog(LOG_ERR, "tcsetpgrp(): %m"); + die(1); + } } #else - /* set process group on tty so we get SIGIO's */ - if (ioctl(fd, TIOCSPGRP, &pgrpid) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSPGRP): %m"); - exit(1); - } + /* 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); + } + if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) { + syslog(LOG_ERR, "fcntl(F_SETFL, FNDELAY | FASYNC): %m"); + die(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); -#ifdef STREAMS - mask |= sigmask(SIGPOLL); -#endif + /* + * 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 (;;) { + sigpause(0); /* Wait for next signal */ + } +} - sv.sv_handler = hup; /* Hangup */ - sv.sv_mask = mask; - sv.sv_flags = 0; - if (sigvec(SIGHUP, &sv, NULL)) { - syslog(LOG_ERR, "sigvec(SIGHUP)"); - exit(1); - } - sv.sv_handler = intr; /* Interrupt */ - sv.sv_mask = mask; - sv.sv_flags = 0; - if (sigvec(SIGINT, &sv, NULL)) { - syslog(LOG_ERR, "sigvec(SIGINT)"); - exit(1); - } - sv.sv_handler = term; /* Terminate */ - sv.sv_mask = mask; - sv.sv_flags = 0; - if (sigvec(SIGTERM, &sv, NULL)) { - syslog(LOG_ERR, "sigvec(SIGTERM)"); - exit(1); - } - sv.sv_handler = alrm; /* Timeout */ - sv.sv_mask = mask; - sv.sv_flags = 0; - if (sigvec(SIGALRM, &sv, NULL)) { - syslog(LOG_ERR, "sigvec(SIGALRM)"); - exit(1); - } - sv.sv_handler = io; /* Input available */ - sv.sv_mask = mask; - sv.sv_flags = 0; - if (sigvec(SIGIO, &sv, NULL)) { - syslog(LOG_ERR, "sigvec(SIGIO)"); - exit(1); - } -#ifdef STREAMS - sv.sv_handler = io; /* Input available */ - sv.sv_mask = mask; - sv.sv_flags = 0; - if (sigvec(SIGPOLL, &sv, NULL)) { - syslog(LOG_ERR, "sigvec(SIGPOLL)"); - exit(1); - } -#endif +#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) -#ifdef __STDC__ - /* Increment debug flag */ - (void) signal(SIGUSR1, (void (*)(int))incdebug); - /* Reset debug flag */ - (void) signal(SIGUSR2, (void (*)(int))nodebug); #else - /* Increment debug flag */ - (void) signal(SIGUSR1, (void (*)())incdebug); - /* Reset debug flag */ - (void) signal(SIGUSR2, (void (*)())nodebug); +/* + * List of valid speeds. + */ +struct speed { + int speed_int, speed_val; +} speeds[] = { +#ifdef B50 + { 50, B50 }, #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"); - exit(1); - } - if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) { - syslog(LOG_ERR, "fcntl(F_SETFL, FNDELAY | FASYNC): %m"); - exit(1); - } - - /* - * Block all signals, start opening the connection, and wait for - * incoming signals (reply, timeout, etc.). - */ - syslog(LOG_INFO, "Connect: %s <--> %s", ifname, devname); - 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); /* Disallow signals */ - upap_authwithpeer(0); - } - } +#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 } +}; + +/* + * 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); + return 0; } +#endif -set_up_tty(fd, flow) -int fd; -int flow; +/* + * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, + * at the requested speed, etc. + */ +set_up_tty(fd) + int fd; { -#ifdef STREAMS - int new_cflag; - struct termios tios; - - if(ioctl(fd, TCGETS, (caddr_t) &tios) < 0) { - syslog(LOG_ERR, "ioctl(TCGETS): %m"); - exit(1); - } - - new_cflag = CS8 | CREAD | HUPCL; - new_cflag |= inspeed ? inspeed : (tios.c_cflag & CBAUD); - if (flow) - new_cflag |= crtscts ? CRTSCTS : 0; - - tios.c_cflag = new_cflag; - tios.c_iflag = IGNBRK | IGNPAR; - tios.c_oflag = 0; - tios.c_lflag = 0; - - if(ioctl(fd, TCSETS, (caddr_t) &tios) < 0) { - syslog(LOG_ERR, "ioctl(TCSETS): %m"); - exit(1); - } -#else -#ifdef SGTTY - struct sgttyb sgttyb; - - /* - * Put the tty in raw mode and set the discipline to PPP. - */ - if (ioctl(fd, TIOCGETP, &initsgttyb) < 0) { - syslog(LOG_ERR, "ioctl(TIOCGETP): %m"); - exit(1); - } - - sgttyb = initsgttyb; - sgttyb.sg_flags = RAW | ANYP; - if (inspeed) - sgttyb.sg_ispeed = inspeed; - - if (ioctl(fd, TIOCSETP, &sgttyb) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETP): %m"); - exit(1); - } -#else +#ifndef SGTTY + int speed; struct termios tios; - if (ioctl(fd, TIOCGETA, &tios) < 0) { - syslog(LOG_ERR, "ioctl(TIOCGETA): %m"); - exit(1); + if (tcgetattr(fd, &tios) < 0) { + syslog(LOG_ERR, "tcgetattr: %m"); + die(1); } - inittermios = tios; + if (!restore_term) + inittermios = tios; - tios.c_cflag = CREAD | CS8 | HUPCL; - if (flow) - tios.c_cflag |= crtscts ? CRTSCTS : 0; + tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL | CRTSCTS); + tios.c_cflag |= CS8 | CREAD | HUPCL; + if (crtscts) + tios.c_cflag |= CRTSCTS; + if (!modem) + tios.c_cflag |= CLOCAL; tios.c_iflag = IGNBRK | IGNPAR; tios.c_oflag = 0; tios.c_lflag = 0; - tios.c_cc[VERASE] = tios.c_cc[VKILL] = 0; tios.c_cc[VMIN] = 1; tios.c_cc[VTIME] = 0; - if (inspeed) { - tios.c_ispeed = inspeed; - tios.c_ospeed = inspeed; + speed = translate_speed(inspeed); + if (speed) { + cfsetospeed(&tios, speed); + cfsetispeed(&tios, speed); } - if (ioctl(fd, TIOCSETA, &tios) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETA): %m"); - exit(1); + if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { + syslog(LOG_ERR, "tcsetattr: %m"); + die(1); + } +#else /* SGTTY */ + int speed; + struct sgttyb sgttyb; + + /* + * Put the tty in raw mode. + */ + if (ioctl(fd, TIOCGETP, &sgttyb) < 0) { + syslog(LOG_ERR, "ioctl(TIOCGETP): %m"); + die(1); + } + + if (!restore_term) + initsgttyb = sgttyb; + + sgttyb.sg_flags = RAW | ANYP; + speed = translate_speed(inspeed); + if (speed) + sgttyb.sg_ispeed = speed; + + if (ioctl(fd, TIOCSETP, &sgttyb) < 0) { + syslog(LOG_ERR, "ioctl(TIOCSETP): %m"); + die(1); } #endif -#endif + restore_term = TRUE; } + /* * quit - Clean up state and exit. */ void - quit() +quit() { - syslog(LOG_NOTICE, "Quitting"); + die(0); +} - if (fd == 0) - return; +/* + * die - like quit, except we can specify an exit status. + */ +void +die(status) + int status; +{ + cleanup(0, NULL); + syslog(LOG_INFO, "Exit."); + exit(status); +} - if (fcntl(fd, F_SETFL, initfdflags) == -1) { - syslog(LOG_ERR, "fcntl(F_SETFL, fdflags): %m"); - exit(1); - } +/* + * cleanup - restore anything which needs to be restored before we exit + */ +/* ARGSUSED */ +void +cleanup(status, arg) + int status; + caddr_t arg; +{ + if (fd != 0) { + /* drop dtr to hang up */ + if (modem) + setdtr(fd, FALSE); -#ifdef STREAMS - str_restore(); -#else -#ifdef SGTTY - if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETP)"); - exit(1); - } -#else - if (ioctl(fd, TIOCSETA, &inittermios) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETA)"); - exit(1); - } + if (fcntl(fd, F_SETFL, initfdflags) < 0) + syslog(LOG_ERR, "fcntl(F_SETFL, fdflags): %m"); -#endif - if (ioctl(fd, TIOCSETD, &initdisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD)"); - exit(1); - } -#endif + disestablish_ppp(); - /* drop dtr to hang up */ - setdtr(fd, FALSE); + if (restore_term) { +#ifndef SGTTY + if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) + syslog(LOG_ERR, "tcsetattr: %m"); +#else + if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) + syslog(LOG_ERR, "ioctl(TIOCSETP): %m"); +#endif + } - close(fd); - fd = 0; + close(fd); + fd = 0; + } - exit(0); + if (pidfilename[0] != 0 && unlink(pidfilename) < 0) + syslog(LOG_WARNING, "unable to unlink pid file: %m"); + pidfilename[0] = 0; } static struct callout *callout = NULL; /* Callout list */ static 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) - void (*func)(); - caddr_t arg; - int time; +void +timeout(func, arg, time) + void (*func)(); + caddr_t arg; + int time; { - struct itimerval itv; - struct callout *newp, **oldpp; + struct itimerval itv; + struct callout *newp, **oldpp; - MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.", - (int) func, (int) arg, time)) + MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.", + (int) func, (int) arg, time)); - /* - * Allocate timeout. - */ - if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) { - syslog(LOG_ERR, "Out of memory in timeout()!"); - exit(1); - } - newp->c_arg = arg; - newp->c_func = func; + /* + * Allocate timeout. + */ + if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) { + syslog(LOG_ERR, "Out of memory in timeout()!"); + die(1); + } + newp->c_arg = arg; + newp->c_func = func; - /* - * 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; + /* + * 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; - MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds.", - itv.it_value.tv_sec)) - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL)"); - exit(1); - } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday"); - exit(1); + /* + * 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.", + 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); + } } - } } /* * untimeout - Unschedule a timeout. */ -void untimeout(func, arg) - void (*func)(); - caddr_t arg; +void +untimeout(func, arg) + void (*func)(); + caddr_t arg; { + struct itimerval itv; + struct callout **copp, *freep; + int reschedule = 0; - struct itimerval itv; - struct callout **copp, *freep; - int reschedule = 0; + MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg)); - 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; + /* + * 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; - (void) free((char *) freep); - break; - } + /* + * 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; + (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.", - itv.it_value.tv_sec)) - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL)"); - exit(1); - } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday"); - exit(1); + 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.", + 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); + } } - } } @@ -934,60 +813,29 @@ void untimeout(func, arg) * adjtimeout - Decrement the first timeout by the amount of time since * it was scheduled. */ -void adjtimeout() +void +adjtimeout() { - struct timeval tv; - int timediff; + 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"); - exit(1); - } - timediff = tv.tv_sec - schedtime.tv_sec; - if (timediff < 0 || - timediff > callout->c_time + 1) - return; + 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); + } + 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; -{ -#ifdef STREAMS - struct strbuf str; - - str.len = len; - str.buf = (caddr_t) p; - if(putmsg(fd, NULL, &str, 0) < 0) { - syslog(LOG_ERR, "putmsg"); - exit(1); - } -#else - if (unit != 0) { - MAINDEBUG((LOG_WARNING, "output: unit != 0!")) - abort(); - } - - if (write(fd, p, len) < 0) { - syslog(LOG_ERR, "write"); - exit(1); - } -#endif + callout->c_time -= timediff; /* OK, Adjust time */ } @@ -998,14 +846,18 @@ int len; */ /*ARGSUSED*/ static void - hup(sig, code, scp, addr) -int sig, code; -struct sigcontext *scp; -char *addr; +hup(sig, code, scp, addr) + int sig, code; + struct sigcontext *scp; + char *addr; { - syslog(LOG_NOTICE, "Hangup (SIGHUP)"); - adjtimeout(); /* Adjust timeouts */ - lcp_lowerdown(0); /* Reset connection */ + syslog(LOG_INFO, "Hangup (SIGHUP)"); + + 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 */ } @@ -1016,14 +868,15 @@ char *addr; */ /*ARGSUSED*/ static void - term(sig, code, scp, addr) -int sig, code; -struct sigcontext *scp; -char *addr; +term(sig, code, scp, addr) + int sig, code; + struct sigcontext *scp; + char *addr; { - syslog(LOG_NOTICE, "Terminate signal received."); - adjtimeout(); /* Adjust timeouts */ - lcp_close(0); /* Close connection */ + syslog(LOG_INFO, "Terminating link."); + persist = 0; /* don't try to restart */ + adjtimeout(); /* Adjust timeouts */ + lcp_close(0); /* Close connection */ } @@ -1034,14 +887,15 @@ char *addr; */ /*ARGSUSED*/ static void - intr(sig, code, scp, addr) -int sig, code; -struct sigcontext *scp; -char *addr; +intr(sig, code, scp, addr) + int sig, code; + struct sigcontext *scp; + char *addr; { - syslog(LOG_NOTICE, "Interrupt received. Exiting."); - adjtimeout(); /* Adjust timeouts */ - lcp_close(0); /* Close connection */ + syslog(LOG_INFO, "Interrupt received: terminating link"); + persist = 0; /* don't try to restart */ + adjtimeout(); /* Adjust timeouts */ + lcp_close(0); /* Close connection */ } @@ -1052,47 +906,47 @@ char *addr; */ /*ARGSUSED*/ static void - alrm(sig, code, scp, addr) -int sig, code; -struct sigcontext *scp; -char *addr; +alrm(sig, code, scp, addr) + int sig, code; + struct sigcontext *scp; + char *addr; { - struct itimerval itv; - struct callout *freep; - - MAINDEBUG((LOG_DEBUG, "Alarm")) - - /* - * 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); - (void) free((char *) freep); - if (callout && 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; - MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds.", - itv.it_value.tv_sec)) - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL)"); - exit(1); + struct itimerval itv; + struct callout *freep; + + MAINDEBUG((LOG_DEBUG, "Alarm")); + + /* + * 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); + (void) free((char *) freep); + if (callout && callout->c_time) + break; } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday"); - exit(1); + + /* + * 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.", + 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); + } } - } } @@ -1103,161 +957,112 @@ char *addr; */ /*ARGSUSED*/ static void - io(sig, code, scp, addr) -int sig, code; -struct sigcontext *scp; -char *addr; +io(sig, code, scp, addr) + int sig, code; + struct sigcontext *scp; + char *addr; { - int len, i; - u_char *p; - u_short protocol; - fd_set fdset; - struct timeval notime; - int ready; -#ifdef STREAMS - struct strbuf str; -#endif + 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 */ + + /* we do this to see if the SIGIO handler is being invoked for input */ + /* ready, or for the socket buffer hitting the low-water mark. */ + + notime.tv_sec = 0; + notime.tv_usec = 0; + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + + if ((ready = select(32, &fdset, (fd_set *) NULL, (fd_set *) NULL, + ¬ime)) == -1) { + syslog(LOG_ERR, "Error in io() select: %m"); + die(1); + } + + if (ready == 0) { + MAINDEBUG((LOG_DEBUG, "IO non-input ready SIGIO occured.")); + return; + } + /* Yup, this is for real */ + for (;;) { /* Read all available packets */ + p = inpacket_buf; /* point to beginning of packet buffer */ - MAINDEBUG((LOG_DEBUG, "IO signal received")) - adjtimeout(); /* Adjust timeouts */ + len = read_packet(inpacket_buf); + if (len < 0) + return; - /* we do this to see if the SIGIO handler is being invoked for input */ - /* ready, or for the socket buffer hitting the low-water mark. */ + if (len == 0) { + syslog(LOG_ERR, "End of file on fd!"); + die(1); + } - notime.tv_sec = 0; - notime.tv_usec = 0; + if (len < DLLHEADERLEN) { + MAINDEBUG((LOG_INFO, "io(): Received short packet.")); + return; + } - FD_ZERO(&fdset); - FD_SET(fd, &fdset); - - if ((ready = select(32, &fdset, (fd_set *) NULL, (fd_set *) NULL, - ¬ime)) == -1) { - syslog(LOG_ERR, "Error in io() select: %m"); - exit(1); - } - - if (ready == 0) { - MAINDEBUG((LOG_DEBUG, "IO non-input ready SIGIO occured.")); - 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.")); + if (debug) + dumpbuffer(inpacket_buf, len + DLLHEADERLEN, LOG_INFO); + return; + } - /* Yup, this is for real */ - for (;;) { /* Read all available packets */ - p = inpacket_buf; /* point to beggining of packet buffer */ + /* + * 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; + } -#ifdef STREAMS - str.maxlen = MTU+DLLHEADERLEN; - str.buf = (caddr_t) p; - i = 0; - len = getmsg(fd, NULL, &str, &i); - if(len < 0) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { - return; - } - syslog(LOG_ERR, "getmsg(fd) %m"); - exit(1); - } - else if(len) - MAINDEBUG((LOG_DEBUG, "getmsg returns with length 0x%x",len)) - - if(str.len < 0) { - MAINDEBUG((LOG_DEBUG, "getmsg short return length %d", - str.len)) - return; - } - - len = str.len; -#else - if ((len = read(fd, p, MTU + DLLHEADERLEN)) < 0) { - if (errno == EWOULDBLOCK) { - MAINDEBUG((LOG_DEBUG, "read(fd): EWOULDBLOCK")) - return; - } - else { - syslog(LOG_ERR, "read(fd): %m"); - exit(1); - } - } - else -#endif - if (len == 0) { - syslog(LOG_ERR, "End of file on fd!"); - exit(1); - } - - 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 != OPEN) { - MAINDEBUG((LOG_INFO, "io(): Received non-LCP packet and LCP is not in open state.")) - dumpbuffer(inpacket_buf, len + DLLHEADERLEN, LOG_ERR); - 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); - p -= DLLHEADERLEN; - len += DLLHEADERLEN; - lcp_sprotrej(0, p, len); + if (i == sizeof (prottbl) / sizeof (struct protent)) { + syslog(LOG_WARNING, "input: Unknown protocol (%x) received!", + protocol); + lcp_sprotrej(0, p - DLLHEADERLEN, len + DLLHEADERLEN); + } } - } } /* - * cleanup - clean_up before we exit - */ -/* ARGSUSED */ -static void - cleanup(status, arg) -int status; -caddr_t arg; -{ - adjtimeout(); - lcp_lowerdown(0); - if (unlink(pidfilename) < 0) - syslog(LOG_WARNING, "unable to unlink pid file: %m"); -} - - -/* * demuxprotrej - Demultiplex a Protocol-Reject. */ void - demuxprotrej(unit, protocol) -int unit; -u_short protocol; +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); + 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); } @@ -1268,14 +1073,12 @@ u_short protocol; */ /*ARGSUSED*/ static void - incdebug(sig, code, scp, addr) -int sig, code; -struct sigcontext *scp; -char *addr; +incdebug(sig) + int sig; { - syslog(LOG_NOTICE, "Debug turned ON, Level %d", debug); - setlogmask(LOG_UPTO(LOG_DEBUG)); - debug++; + syslog(LOG_INFO, "Debug turned ON, Level %d", debug); + setlogmask(LOG_UPTO(LOG_DEBUG)); + debug++; } @@ -1286,913 +1089,82 @@ char *addr; */ /*ARGSUSED*/ static void - nodebug(sig, code, scp, addr) -int sig, code; -struct sigcontext *scp; -char *addr; -{ - setlogmask(LOG_UPTO(LOG_WARNING)); - debug = 0; -} - - -/* - * setdebug - Set debug (command line argument). - */ -static int - setdebug(argcp, argvp) -int *argcp; -char ***argvp; -{ - debug++; - setlogmask(LOG_UPTO(LOG_DEBUG)); - --*argcp, ++*argvp; - return (1); -} - -/* - * noopt - Disable all options. - */ -static int - noopt(argcp, argvp) -int *argcp; -char ***argvp; +nodebug(sig) + int sig; { - 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)); - --*argcp, ++*argvp; - return (1); -} - - -/* - * setconnector - Set a program to connect to a serial line - */ -static int - setconnector(argcp, argvp) -int *argcp; -char ***argvp; -{ - - --*argcp, ++*argvp; - - connector = strdup(**argvp); - if (connector == NULL) { - syslog(LOG_ERR, "cannot allocate space for connector string"); - exit(1); - } - - --*argcp, ++*argvp; - return (1); + setlogmask(LOG_UPTO(LOG_WARNING)); + debug = 0; } /* * set_up_connection - run a program to initialize the serial connector */ -int set_up_connection(program, in, out) - char *program; - int in, out; -{ - int pid; - int flags; - int status; - - flags = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)); - pid = fork(); - - if (pid < 0) { - syslog(LOG_ERR, "fork"); - exit(1); - } - - if (pid == 0) { - (void) setreuid(getuid(), getuid()); - (void) setregid(getgid(), getgid()); - (void) sigsetmask(flags); - (void) dup2(in, 0); - (void) dup2(out, 1); - (void) execl("/bin/sh", "sh", "-c", program, (char *)0); - syslog(LOG_ERR, "could not exec /bin/sh"); - _exit(99); - } - else { - while (waitpid(pid, &status, 0) != pid) { - if (errno == EINTR) - continue; - syslog(LOG_ERR, "waiting for connection process"); - exit(1); - } - (void) sigsetmask(flags); - } - return (status == 0 ? 0 : -1); -} - -/* - * noaccomp - Disable Address/Control field compression negotiation. - */ -static 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. - */ -static 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. - */ -static 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. - */ -static 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. - */ -static int - nomru(argcp, argvp) -int *argcp; -char ***argvp; -{ - lcp_wantoptions[0].neg_mru = 0; - lcp_allowoptions[0].neg_mru = 0; - --*argcp, ++*argvp; - return (1); -} - - -/* - * setmru - Set MRU for negotiation. - */ -static int - setmru(argcp, argvp) -int *argcp; -char ***argvp; -{ - --*argcp, ++*argvp; - lcp_wantoptions[0].mru = atoi(**argvp); - --*argcp, ++*argvp; - return (1); -} - - -/* - * nopcomp - Disable Protocol field compression negotiation. - */ -static 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. - */ -static int - setpassive(argcp, argvp) -int *argcp; -char ***argvp; -{ - lcp_wantoptions[0].passive = 1; - --*argcp, ++*argvp; - return (1); -} - - -/* - * noupap - Disable UPAP authentication. - */ -static int - noupap(argcp, argvp) -int *argcp; -char ***argvp; -{ - lcp_allowoptions[0].neg_upap = 0; - --*argcp, ++*argvp; - return (1); -} - - -/* - * requpap - Require UPAP authentication. - */ -static int - requpap(argcp, argvp) -int *argcp; -char ***argvp; -{ - FILE * ufile; - struct stat sbuf; - - lcp_wantoptions[0].neg_upap = 1; - lcp_allowoptions[0].neg_upap = 0; - --*argcp, ++*argvp; - strcpy(uinfopath, **argvp); - --*argcp, ++*argvp; - - /* open user info file */ - - if ((ufile = fopen(uinfopath, "r")) == NULL) { - fprintf(stderr, "unable to open user login data file %s\n", uinfopath); - exit(1); - }; - - if (fstat(fileno(ufile), &sbuf) < 0) { - perror("cannot stat user login data file!"); - exit(1); - } - if ((sbuf.st_mode & 077) != 0) - syslog(LOG_WARNING, "Warning - user info file has world and/or group access!\n"); - - /* get username */ - fgets(user, sizeof (user) - 1, ufile); - if (strlen(user) == 0) { - fprintf(stderr, "Unable to get user name from user login data file.\n"); - exit(2); - } - /* get rid of newline */ - user[strlen(user) - 1] = '\000'; - - fgets(passwd, sizeof(passwd) - 1, ufile); - - if (strlen(passwd) == 0) { - fprintf(stderr, "Unable to get password from user login data file.\n"); - exit(2); - } - - passwd[strlen(passwd) - 1] = '\000'; - - return (1); -} - - -/* - * nochap - Disable CHAP authentication. - */ -static int - nochap(argcp, argvp) -int *argcp; -char ***argvp; -{ - lcp_allowoptions[0].neg_chap = 0; - --*argcp, ++*argvp; - return (1); -} - - -/* - * reqchap - Require CHAP authentication. - */ -static int - reqchap(argcp, argvp) -int *argcp; -char ***argvp; -{ - lcp_wantoptions[0].neg_chap = 1; - lcp_allowoptions[0].neg_chap = 0; - --*argcp, ++*argvp; - return (1); -} - - -/* - * setvjmode - Set vj compression mode - */ - -static int - setvjmode(argcp, argvp) -int *argcp; -char ***argvp; -{ - extern int ipcp_vj_mode; - - --*argcp, ++*argvp; - - if (!strcmp(**argvp, "old")) { /* "old" mode */ - ipcp_vj_setmode(IPCP_VJMODE_OLD); - } - - else if (!strcmp(**argvp, "rfc1172")) { /* "rfc1172" mode*/ - ipcp_vj_setmode(IPCP_VJMODE_RFC1172); - } - - else if (!strcmp(**argvp, "rfc1332")) { /* "rfc1332" default mode */ - ipcp_vj_setmode(IPCP_VJMODE_RFC1332); - } - else { - syslog(LOG_WARNING, - "Unknown vj compression mode %s. Defaulting to RFC1332", **argvp); - ipcp_vj_setmode(IPCP_VJMODE_RFC1332); - } - --*argcp, ++*argvp; - - return (1); -} -/* - * setnovj - diable vj compression - */ - -static int - setnovj(argcp, argvp) -int *argcp; -char ***argvp; -{ - extern int ipcp_vj_mode; - - --*argcp, ++*argvp; - ipcp_wantoptions[0].neg_vj = 0; - ipcp_allowoptions[0].neg_vj = 0; - - return (1); -} - -/* - * setdomain - Set domain name to append to hostname - */ -static int - setdomain(argcp, argvp) -int *argcp; -char ***argvp; -{ - - --*argcp, ++*argvp; - - strcat(hostname, **argvp); - hostname_len = strlen(hostname); - - --*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 -#ifdef B57600 - { 57600, B57600 }, -#endif -#ifdef B115200 - { 115200, B115200 }, -#endif - { 0, 0 } -}; - -static int - setasyncmap(argcp, argvp) -int *argcp; -char ***argvp; -{ - unsigned long asyncmap; - - asyncmap = 0xffffffff; - ++*argvp; - sscanf(**argvp,"%lx",&asyncmap); - ++*argvp; - lcp_wantoptions[0].asyncmap = asyncmap; - *argcp -= 2; - return(1); -} - -/* - * setspeed - Set the speed. - */ -static int - setspeed(argcp, argvp) -int *argcp; -char ***argvp; +int +set_up_connection(program, in, out) + char *program; + int in, out; { - 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); -} + int pid; + int status; + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGHUP); + sigprocmask(SIG_BLOCK, &mask, &mask); -/* - * setdevname - Set the device name. - */ -int setdevname(argcp, argvp) - int *argcp; - char ***argvp; -{ - char dev[DEVNAME_SIZE]; - 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); - syslog(LOG_ERR, cp); - exit(1); - } - - (void) strcpy(devname, cp); - default_device = FALSE; - --*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. - */ - if ((tty = ttyname(fileno(stdin))) == NULL) - tty = ""; /* running from init means no stdin. Null kills strcmp -KWK */ - 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 IP address - */ -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); + pid = fork(); - /* - * 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) { - syslog(LOG_WARNING, "unknown host: %s", **argvp); - goto ret; - } - bcopy(hp->h_addr, (char *) &local, hp->h_length); + if (pid < 0) { + syslog(LOG_ERR, "fork: %m"); + die(1); } - } - /* - * 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) { - syslog(LOG_WARNING,"unknown host: %s", colon); - goto ret; - } - bcopy(hp->h_addr, (char *) &remote, hp->h_length); + if (pid == 0) { + setreuid(getuid(), getuid()); + setregid(getgid(), getgid()); + sigprocmask(SIG_SETMASK, &mask, NULL); + dup2(in, 0); + dup2(out, 1); + execl("/bin/sh", "sh", "-c", program, (char *)0); + syslog(LOG_ERR, "could not exec /bin/sh: %m"); + _exit(99); + /* NOTREACHED */ } - } - - ipcp_wantoptions[0].neg_addrs = 1; - ipcp_wantoptions[0].ouraddr = local; - ipcp_wantoptions[0].hisaddr = remote; - - ret: - --*argcp, ++*argvp; - return (1); -} - -static int - setnetmask(argcp, argvp) -int *argcp; -char ***argvp; -{ - u_long mask; - - --*argcp, ++*argvp; - if ((mask = inet_addr(**argvp)) == -1) { - fprintf(stderr, "Invalid netmask %s\n", **argvp); - exit(1); - } - - netmask = mask; - --*argcp, ++*argvp; - return (1); -} - -static int - setcrtscts(argcp, argvp) -int *argcp; -char ***argvp; -{ - crtscts = 1; - --*argcp, ++*argvp; - return (1); -} - -static int - setnodetach(argcp, argvp) -int *argcp; -char ***argvp; -{ - nodetach = 1; - --*argcp, ++*argvp; - return (1); -} - -/* - * getuserpasswd - Get the user name and passwd. - */ -static void - getuserpasswd() -{ - - upap[0].us_user = user; - upap[0].us_userlen = strlen(upap[0].us_user); - upap[0].us_passwd = passwd; - 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(); - char *tmp_passwd, *tmp_user; - - /* why alloca.h doesn't define what alloca() returns is a mystery */ - /* seems to be defined in stdlib.h for FreeBSD, rgrimes */ - -#ifdef sparc - char *__builtin_alloca __ARGS((int)); -#else -#ifndef __386BSD__ - char *alloca __ARGS((int)); -#endif /* !__386BSD__ */ -#endif /*sparc*/ - tmp_passwd = alloca(passwdlen + 1); /* we best make copies before */ - /* null terminating the string */ - if (tmp_passwd == NULL) { - syslog(LOG_ERR, "alloca failed"); - exit(1); - } - bcopy(passwd, tmp_passwd, passwdlen); - tmp_passwd[passwdlen] = '\0'; - - tmp_user = alloca(userlen + 1); - if (tmp_user == NULL) { - syslog(LOG_ERR, "alloca failed"); - exit(1); - } - bcopy(user, tmp_user, userlen); - tmp_user[userlen] = '\0'; - - if ((pw = getpwnam(tmp_user)) == NULL) { - *msg = "Login incorrect"; - *msglen = strlen(*msg); - syslog(LOG_WARNING, "upap login userid '%s' incorrect",tmp_user); - 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(tmp_passwd, pw->pw_passwd); - if (strcmp(epasswd, pw->pw_passwd)) { - *msg = "Login incorrect"; - *msglen = strlen(*msg); - syslog(LOG_WARNING, "upap login password '%s' incorrect", tmp_passwd); - /* - * 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_WARNING, "%d LOGIN FAILURES ON %s, %s", - attempts, devname, tmp_user); - lcp_close(0); /* Drop DTR? */ + while (waitpid(pid, &status, 0) != pid) { + if (errno == EINTR) + continue; + syslog(LOG_ERR, "waiting for connection process: %m"); + die(1); } - if (attempts > 3) - sleep((u_int) (attempts - 3) * 5); - return (UPAP_AUTHNAK); - } - - attempts = 0; /* Reset count */ - *msg = "Login ok"; - *msglen = strlen(*msg); - syslog(LOG_NOTICE, "user %s logged in", tmp_user); - tty = rindex(devname, '/'); - if (tty == NULL) - tty = devname; - else - tty++; - logwtmp(tty, tmp_user, ""); /* Add wtmp login entry */ - - return (UPAP_AUTHACK); -} - + sigprocmask(SIG_SETMASK, &mask, NULL); -/* - * logout - Logout the user. - */ -void logout() -{ - char *tty; - - tty = rindex(devname, '/'); - if (tty == NULL) - tty = devname; - else - tty++; - logwtmp(tty, "", ""); /* Add wtmp logout entry */ + return (status == 0 ? 0 : -1); } /* - * 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) == NULL) { - if (feof(fp)) - break; - else { - syslog(LOG_ERR, "fgets"); - exit(1); - } - } - if ((s = index(buf, ' ')) == NULL) - continue; - *s++ = '\0'; - if (!strcmp(user, buf)) { - rc = 1; - break; - } - } - fclose(fp); - return (rc); -} -/* - * open "secret" file and return the secret matching the given name. - * If no secret for a given name is found, use the one for "default". - */ - -void - get_secret(name, secret, secret_len) -u_char * name; -u_char * secret; -int * secret_len; -{ - FILE * sfile; - struct stat sbuf; - u_char fname[256]; - int match_found, default_found; - - match_found = FALSE; - default_found = FALSE; - - if ((sfile = fopen(_PATH_CHAPFILE, "r")) == NULL) { - syslog(LOG_ERR, "unable to open secret file %s", _PATH_CHAPFILE); - exit(1); - }; - - if (fstat(fileno(sfile), &sbuf) < 0) { - syslog(LOG_ERR, "cannot stat secret file!: %m"); - exit(1); - } - if ((sbuf.st_mode & 077) != 0) - syslog(LOG_WARNING, "Warning - secret file has world and/or group access!"); - - while (!feof(sfile) && !match_found) { - if (fscanf(sfile, "%s %s", fname, secret) == EOF) - break; - if (!strcasecmp((char *)fname, (char *)name)) { - match_found = TRUE; - } - if (!strcasecmp("default", (char *)name)) { - default_found = TRUE; - } - } - - if (!match_found && !default_found) { - syslog(LOG_ERR, "No match or default entry found for %s in CHAP secret file! Aborting...", name); - cleanup(0, NULL); /* shut us down */ - } -#ifdef UNSECURE -/* while this is useful for debugging, it is a security hole as well */ - - syslog(LOG_DEBUG, "get_secret: found secret %s", secret); -#endif /*UNSECURE*/ - fclose(sfile); - *secret_len = strlen((char *)secret); - if (*secret_len > MAX_SECRET_LEN) { /* don't let it overflow the buffer */ - syslog(LOG_ERR, "Length of secret for host %s is greater than the maximum %d characters! ", name, MAX_SECRET_LEN); - cleanup(0, NULL); /* scream and die */ - } - return; -} -/* * Return user specified netmask. A value of zero means no netmask has * been set. */ /* ARGSUSED */ u_long - GetMask(addr) -u_long addr; +GetMask(addr) + u_long addr; { - return(netmask); + return(netmask); } -#ifdef STREAMS -/* - * this module will attempt to reconstruct the stream with the - * previously popped modules +/* + * dumpbuffer - print contents of a buffer in hex to standard output. */ - -/*ARGSUSED*/ -static void - str_restore() -{ - /*EMPTY*/ - while(ioctl(fd, I_POP, 0) == 0); /* pop any we pushed */ - - for(; str_module_count > 0; str_module_count--) { - if(ioctl(fd, I_PUSH, str_modules[str_module_count-1].modname)) { - syslog(LOG_ERR, "str_restore: couldn't push module %s: %m", - str_modules[str_module_count-1].modname); - } - else { - MAINDEBUG((LOG_INFO, "str_restore: pushed module %s", - str_modules[str_module_count-1].modname)) - } - } -} -#endif - +void dumpbuffer(buffer, size, level) -unsigned char *buffer; -int size; -int level; + unsigned char *buffer; + int size; + int level; { register int i; char line[256], *p; @@ -2227,48 +1199,17 @@ int level; } } -#ifdef sun -setdtr(fd, on) -int fd, on; -{ - int linestate; - - ioctl(fd, TIOCMGET, &linestate); - - if (on) - linestate |= TIOCM_DTR; - else - linestate &= ~TIOCM_DTR; - ioctl(fd, TIOCMSET, &linestate); -} -#endif -#ifdef __386BSD__ +/* + * 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; - if (on) - ioctl(fd, TIOCMBIS, &modembits); - else - ioctl(fd, TIOCMBIC, &modembits); -} -#endif - -char * -proto_name(proto) -u_short proto; -{ - switch (proto) { - case LCP: return "lcp"; - case UPAP: return "pap"; - case CHAP: return "chap"; - case IPCP: return "ipcp"; -#define LQM 0xc025 - case LQM: return "lqm"; - } - return "<unknown>"; + ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); } #include <varargs.h> @@ -2296,3 +1237,11 @@ va_dcl line[0] = 0; } } + +void +novm(msg) + char *msg; +{ + syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg); + die(1); +} |