X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fmain.c;h=d278b071d95b3bbc40f13423de2e6db26db8a6bd;hp=4e1e3de522e4ea4dda2dabd9a600e826b4cc4ffa;hb=dee72905271845128ad26cff5cf770c433f3f4a7;hpb=9ec074e3ff0ef6bbdd673bfd199713269748f08d diff --git a/pppd/main.c b/pppd/main.c index 4e1e3de..d278b07 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -18,83 +18,46 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.2 1993/11/23 23:40:53 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.28 1995/10/27 03:41:01 paulus Exp $"; #endif -#define SETSID - #include +#include +#include #include #include #include #include #include #include - -/* - * 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 -#undef SGTTY -#endif - -#ifdef SGTTY -#include -#else -#ifndef sun -#include -#endif -#include -#endif - +#include #include #include +#include +#include +#include #include #include -#include - -#include "callout.h" - #include -#include - -#include - -#ifndef BSD -#define BSD 43 -#endif /*BSD*/ -#include "ppp.h" +#include "pppd.h" #include "magic.h" #include "fsm.h" #include "lcp.h" #include "ipcp.h" #include "upap.h" #include "chap.h" - -#include "pppd.h" +#include "ccp.h" #include "pathnames.h" #include "patchlevel.h" - -#ifndef TRUE -#define TRUE (1) -#endif /*TRUE*/ - -#ifndef FALSE -#define FALSE (0) -#endif /*FALSE*/ - -#ifdef PIDPATH -static char *pidpath = PIDPATH; /* filename in which pid will be stored */ -#else -static char *pidpath = _PATH_PIDFILE; -#endif /* PIDFILE */ +/* + * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless + * /etc/ppp/options exists. + */ +#ifndef REQ_SYSOPTIONS +#define REQ_SYSOPTIONS 1 +#endif /* interface vars */ char ifname[IFNAMSIZ]; /* Interface name */ @@ -102,71 +65,52 @@ int ifunit; /* Interface unit number */ char *progname; /* Name of this program */ char hostname[MAXNAMELEN]; /* Our hostname */ -char our_name[MAXNAMELEN]; -char remote_name[MAXNAMELEN]; - +static char pidfilename[MAXPATHLEN]; /* name of pid file */ +static char default_devnam[MAXPATHLEN]; /* name of default device */ 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) */ +static uid_t uid; /* Our real user-id */ -int fd; /* Device file descriptor */ -int s; /* Socket file descriptor */ +int fd = -1; /* Device file descriptor */ -#ifdef SGTTY -static struct sgttyb initsgttyb; /* Initial TTY sgttyb */ -#else -static struct termios inittermios; /* Initial TTY termios */ -#endif - -static int initfdflags = -1; /* Initial file descriptor flags */ +int phase; /* where the link is at */ +int kill_link; +int open_ccp_flag; -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 */ +u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */ +static u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ int hungup; /* terminal has been hung up */ - -/* configured variables */ - -int debug = 0; /* Debug flag */ -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 *)); -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)); -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 -extern char *ttyname __ARGS((int)); +static int n_children; /* # child processes still running */ + +int baud_rate; /* Actual bits/second for serial device */ + +char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n"; + +/* Prototypes for procedures local to this file. */ + +static void cleanup __P((void)); +static void close_fd __P((void)); +static void get_input __P((void)); +static void calltimeout __P((void)); +static struct timeval *timeleft __P((struct timeval *)); +static void hup __P((int)); +static void term __P((int)); +static void chld __P((int)); +static void toggle_debug __P((int)); +static void open_ccp __P((int)); +static void bad_signal __P((int)); +static int device_script __P((char *, int, int)); +static void reap_kids __P((void)); +static void pr_log __P((void *, char *, ...)); + +extern char *ttyname __P((int)); +extern char *getlogin __P((void)); + +#ifdef ultrix +#undef O_NONBLOCK +#define O_NONBLOCK O_NDELAY #endif -extern char *getlogin __ARGS((void)); /* * PPP Data Link Layer "protocol" table. @@ -177,129 +121,105 @@ static struct protent { void (*init)(); void (*input)(); void (*protrej)(); + int (*printpkt)(); + void (*datainput)(); + char *name; } 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 }, + { PPP_LCP, lcp_init, lcp_input, lcp_protrej, + lcp_printpkt, NULL, "LCP" }, + { PPP_IPCP, ipcp_init, ipcp_input, ipcp_protrej, + ipcp_printpkt, NULL, "IPCP" }, + { PPP_PAP, upap_init, upap_input, upap_protrej, + upap_printpkt, NULL, "PAP" }, + { PPP_CHAP, ChapInit, ChapInput, ChapProtocolReject, + ChapPrintPkt, NULL, "CHAP" }, + { PPP_CCP, ccp_init, ccp_input, ccp_protrej, + ccp_printpkt, ccp_datainput, "CCP" }, }; +#define N_PROTO (sizeof(prottbl) / sizeof(prottbl[0])) main(argc, argv) int argc; char *argv[]; { - int mask, i; - struct sigvec sv; + int i, nonblock, fdflags; + struct sigaction sa; struct cmd *cmdp; FILE *pidfile; char *p; + struct passwd *pw; + struct timeval timo; + sigset_t mask; - /* - * 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)); -#else - openlog("pppd", LOG_PID); -#define LOG_UPTO(x) (x) -#define setlogmask(x) (x) -#endif - -#ifdef STREAMS - p = ttyname(fileno(stdin)); + p = ttyname(0); if (p) - strcpy(devname, p); -#endif - - magic_init(); + strcpy(devnam, p); + strcpy(default_devnam, devnam); if (gethostname(hostname, MAXNAMELEN) < 0 ) { - syslog(LOG_ERR, "couldn't get hostname: %m"); + perror("couldn't get hostname"); die(1); } hostname[MAXNAMELEN-1] = 0; - pid = getpid(); + uid = getuid(); + + if (!ppp_available()) { + fprintf(stderr, no_ppp_msg); + 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++) + for (i = 0; i < N_PROTO; i++) (*prottbl[i].init)(0); progname = *argv; - if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS) || + if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) || !options_from_user() || - !parse_args(argc-1, argv+1)) + !parse_args(argc-1, argv+1) || + !options_for_tty()) 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()); - -#ifdef SETSID /* - * Make sure we can set the serial device to be our controlling terminal. + * If the user has specified the default device name explicitly, + * pretend they hadn't. */ - 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); - } - if (pgrpid != pid) - syslog(LOG_WARNING, "warning... not a process group leader"); + if (!default_device && strcmp(devnam, default_devnam) == 0) + default_device = 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"); - } + /* + * Initialize system-dependent stuff and magic number package. + */ + sys_init(); + magic_init(); - /* create new session */ - if ((pgrpid = setsid()) < 0) { - syslog(LOG_ERR, "setsid(): %m"); - die(1); - } + /* + * Detach ourselves from the terminal, if required, + * and identify who is running us. + */ + if (!default_device && !nodetach && daemon(0, 0) < 0) { + perror("Couldn't detach from controlling terminal"); + exit(1); } -#endif - - /* 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); + pid = getpid(); + p = getlogin(); + if (p == NULL) { + pw = getpwuid(uid); + if (pw != NULL && pw->pw_name != NULL) + p = pw->pw_name; + else + p = "(unknown)"; } + syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d", + VERSION, PATCHLEVEL, p, uid); /* * Compute mask of all interesting signals and install signal handlers @@ -309,318 +229,285 @@ main(argc, argv) sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGALRM); - sigaddset(&mask, SIGIO); -#ifdef STREAMS - sigaddset(&mask, SIGPOLL); -#endif + sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGCHLD); #define SIGNAL(s, handler) { \ - sv.sv_handler = handler; \ - if (sigvec(s, &sv, NULL) < 0) { \ - syslog(LOG_ERR, "sigvec(%d): %m", s); \ + sa.sa_handler = handler; \ + if (sigaction(s, &sa, NULL) < 0) { \ + syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \ die(1); \ } \ } - sv.sv_mask = mask; - sv.sv_flags = 0; + sa.sa_mask = mask; + sa.sa_flags = 0; SIGNAL(SIGHUP, hup); /* Hangup */ - SIGNAL(SIGINT, intr); /* Interrupt */ + SIGNAL(SIGINT, term); /* Interrupt */ SIGNAL(SIGTERM, term); /* Terminate */ - SIGNAL(SIGALRM, alrm); /* Timeout */ - SIGNAL(SIGIO, io); /* Input available */ -#ifdef STREAMS - SIGNAL(SIGPOLL, io); /* Input available */ -#endif + SIGNAL(SIGCHLD, chld); - signal(SIGUSR1, incdebug); /* Increment debug flag */ - signal(SIGUSR2, nodebug); /* Reset debug flag */ - + SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */ + SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */ /* - * Open the serial device and set it up to be the ppp interface. + * Install a handler for other signals which would otherwise + * cause pppd to exit without cleaning up. */ - if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) { - syslog(LOG_ERR, "open(%s): %m", devname); - die(1); - } - hungup = 0; - - /* set device to be controlling tty */ - if (!default_device && ioctl(fd, TIOCSCTTY) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSCTTY): %m"); - die(1); - } + SIGNAL(SIGABRT, bad_signal); + SIGNAL(SIGALRM, bad_signal); + SIGNAL(SIGFPE, bad_signal); + SIGNAL(SIGILL, bad_signal); + SIGNAL(SIGPIPE, bad_signal); + SIGNAL(SIGQUIT, bad_signal); + SIGNAL(SIGSEGV, bad_signal); +#ifdef SIGBUS + SIGNAL(SIGBUS, bad_signal); +#endif +#ifdef SIGEMT + SIGNAL(SIGEMT, bad_signal); +#endif +#ifdef SIGPOLL + SIGNAL(SIGPOLL, bad_signal); +#endif +#ifdef SIGPROF + SIGNAL(SIGPROF, bad_signal); +#endif +#ifdef SIGSYS + SIGNAL(SIGSYS, bad_signal); +#endif +#ifdef SIGTRAP + SIGNAL(SIGTRAP, bad_signal); +#endif +#ifdef SIGVTALRM + SIGNAL(SIGVTALRM, bad_signal); +#endif +#ifdef SIGXCPU + SIGNAL(SIGXCPU, bad_signal); +#endif +#ifdef SIGXFSZ + SIGNAL(SIGXFSZ, bad_signal); +#endif - /* set line speed, flow control, etc. */ - set_up_tty(fd); + /* + * Lock the device if we've been asked to. + */ + if (lockflag && !default_device) + if (lock(devnam) < 0) + die(1); - /* run connection script */ - if (connector) { - syslog(LOG_INFO, "Connecting with <%s>", connector); + do { - /* drop dtr to hang up in case modem is off hook */ - if (!default_device && modem) { - setdtr(fd, FALSE); - sleep(1); - setdtr(fd, TRUE); + /* + * Open the serial device and set it up to be the ppp interface. + * If we're dialling out, or we don't want to use the modem lines, + * we open it in non-blocking mode, but then we need to clear + * the non-blocking I/O bit. + */ + nonblock = (connector || !modem)? O_NONBLOCK: 0; + if ((fd = open(devnam, nonblock | O_RDWR, 0)) < 0) { + syslog(LOG_ERR, "Failed to open %s: %m", devnam); + die(1); } + if (nonblock) { + if ((fdflags = fcntl(fd, F_GETFL)) == -1 + || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) + syslog(LOG_WARNING, + "Couldn't reset non-blocking mode on device: %m"); + } + hungup = 0; + kill_link = 0; - if (set_up_connection(connector, fd, fd) < 0) { - syslog(LOG_ERR, "could not set up connection"); - setdtr(fd, FALSE); - die(1); + /* run connection script */ + if (connector && connector[0]) { + MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); + + /* set line speed, flow control, etc.; set CLOCAL for now */ + set_up_tty(fd, 1); + + /* drop dtr to hang up in case modem is off hook */ + if (!default_device && modem) { + setdtr(fd, FALSE); + sleep(1); + setdtr(fd, TRUE); + } + + if (device_script(connector, fd, fd) < 0) { + syslog(LOG_ERR, "Connect script failed"); + setdtr(fd, FALSE); + die(1); + } + + syslog(LOG_INFO, "Serial connection established."); + sleep(1); /* give it time to set up its terminal */ } - syslog(LOG_INFO, "Connected..."); - sleep(1); /* give it time to set up its terminal */ - } - - /* 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 line speed, flow control, etc.; clear CLOCAL if modem option */ + set_up_tty(fd, 0); - /* - * Set process group of device to our process group so we can get SIGIOs. - */ -#ifdef SETSID - if (default_device) { - int id = tcgetpgrp(fd); - if (id != pgrpid) { - syslog(LOG_WARNING, - "warning: not foreground process group leader"); + /* 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", _PATH_VARRUN, ifname); + if ((pidfile = fopen(pidfilename, "w")) != NULL) { + fprintf(pidfile, "%d\n", pid); + (void) fclose(pidfile); + } else { + syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename); + pidfilename[0] = 0; } - } else { - if (tcsetpgrp(fd, pgrpid) < 0) { - syslog(LOG_ERR, "tcsetpgrp(): %m"); - die(1); + + /* + * Block all signals, start opening the connection, and wait for + * incoming events (reply, timeout, etc.). + */ + syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); + lcp_lowerup(0); + lcp_open(0); /* Start protocol */ + for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) { + wait_input(timeleft(&timo)); + calltimeout(); + get_input(); + if (kill_link) { + lcp_close(0); + kill_link = 0; + } + if (open_ccp_flag) { + if (phase == PHASE_NETWORK) { + ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ + ccp_open(0); + } + open_ccp_flag = 0; + } + reap_kids(); /* Don't leave dead kids lying around */ } - } -#else - /* set process group on tty so we get SIGIO's */ - if (ioctl(fd, TIOCSPGRP, &pgrpid) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSPGRP): %m"); - die(1); - } -#endif - /* - * Record initial device flags, then set device to cause SIGIO - * signals to be generated. - */ - if ((initfdflags = fcntl(fd, F_GETFL)) == -1) { - syslog(LOG_ERR, "fcntl(F_GETFL): %m"); - die(1); - } - if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) { - syslog(LOG_ERR, "fcntl(F_SETFL, FNDELAY | FASYNC): %m"); - die(1); - } - - /* - * Block all signals, start opening the connection, and wait for - * incoming signals (reply, timeout, etc.). - */ - syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devname); - sigprocmask(SIG_BLOCK, &mask, NULL); /* Block signals now */ - lcp_lowerup(0); /* XXX Well, sort of... */ - lcp_open(0); /* Start protocol */ - for (;;) { - sigpause(0); /* Wait for next signal */ - } -} + /* + * Run disconnector script, if requested. + * XXX we may not be able to do this if the line has hung up! + */ + disestablish_ppp(); + if (disconnector) { + set_up_tty(fd, 1); + if (device_script(disconnector, fd, fd) < 0) { + syslog(LOG_WARNING, "disconnect script failed"); + } else { + syslog(LOG_INFO, "Serial link disconnected."); + } + } -#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) + close_fd(); + if (unlink(pidfilename) < 0 && errno != ENOENT) + syslog(LOG_WARNING, "unable to delete pid file: %m"); + pidfilename[0] = 0; -#else -/* - * List of valid speeds. - */ -struct speed { - int speed_int, speed_val; -} speeds[] = { -#ifdef B50 - { 50, B50 }, -#endif -#ifdef B75 - { 75, B75 }, -#endif -#ifdef B110 - { 110, B110 }, -#endif -#ifdef B134 - { 134, B134 }, -#endif -#ifdef B150 - { 150, B150 }, -#endif -#ifdef B200 - { 200, B200 }, -#endif -#ifdef B300 - { 300, B300 }, -#endif -#ifdef B600 - { 600, B600 }, -#endif -#ifdef B1200 - { 1200, B1200 }, -#endif -#ifdef B1800 - { 1800, B1800 }, -#endif -#ifdef B2000 - { 2000, B2000 }, -#endif -#ifdef B2400 - { 2400, B2400 }, -#endif -#ifdef B3600 - { 3600, B3600 }, -#endif -#ifdef B4800 - { 4800, B4800 }, -#endif -#ifdef B7200 - { 7200, B7200 }, -#endif -#ifdef B9600 - { 9600, B9600 }, -#endif -#ifdef B19200 - { 19200, B19200 }, -#endif -#ifdef B38400 - { 38400, B38400 }, -#endif -#ifdef EXTA - { 19200, EXTA }, -#endif -#ifdef EXTB - { 38400, EXTB }, -#endif -#ifdef B57600 - { 57600, B57600 }, -#endif -#ifdef B115200 - { 115200, B115200 }, -#endif - { 0, 0 } -}; + } while (persist); -/* - * 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; + die(0); } -#endif + /* - * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, - * at the requested speed, etc. + * get_input - called when incoming data is available. */ -set_up_tty(fd) - int fd; +static void +get_input() { -#ifndef SGTTY - int speed; - struct termios tios; + int len, i; + u_char *p; + u_short protocol; - if (tcgetattr(fd, &tios) < 0) { - syslog(LOG_ERR, "tcgetattr: %m"); - die(1); + p = inpacket_buf; /* point to beginning of packet buffer */ + + len = read_packet(inpacket_buf); + if (len < 0) + return; + + if (len == 0) { + syslog(LOG_NOTICE, "Modem hangup"); + hungup = 1; + lcp_lowerdown(0); /* serial link is no longer available */ + link_terminated(0); + return; } - if (!restore_term) - inittermios = tios; - - 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[VMIN] = 1; - tios.c_cc[VTIME] = 0; - speed = translate_speed(inspeed); - if (speed) { - cfsetospeed(&tios, speed); - cfsetispeed(&tios, speed); + if (debug /*&& (debugflags & DBG_INPACKET)*/) + log_packet(p, len, "rcvd "); + + if (len < PPP_HDRLEN) { + MAINDEBUG((LOG_INFO, "io(): Received short packet.")); + return; } - if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { - syslog(LOG_ERR, "tcsetattr: %m"); - die(1); + p += 2; /* Skip address and control */ + GETSHORT(protocol, p); + len -= PPP_HDRLEN; + + /* + * Toss all non-LCP packets unless LCP is OPEN. + */ + if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) { + MAINDEBUG((LOG_INFO, + "io(): Received non-LCP packet when LCP not open.")); + return; } -#else /* SGTTY */ - int speed; - struct sgttyb sgttyb; /* - * Put the tty in raw mode. + * Upcall the proper protocol input routine. */ - if (ioctl(fd, TIOCGETP, &sgttyb) < 0) { - syslog(LOG_ERR, "ioctl(TIOCGETP): %m"); - die(1); + for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) { + if (prottbl[i].protocol == protocol) { + (*prottbl[i].input)(0, p, len); + return; + } + if (protocol == (prottbl[i].protocol & ~0x8000) + && prottbl[i].datainput != NULL) { + (*prottbl[i].datainput)(0, p, len); + return; + } } - if (!restore_term) - initsgttyb = sgttyb; + if (debug) + syslog(LOG_WARNING, "Unknown protocol (0x%x) received", protocol); + lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); +} - 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 - restore_term = TRUE; +/* + * demuxprotrej - Demultiplex a Protocol-Reject. + */ +void +demuxprotrej(unit, protocol) + int unit; + u_short protocol; +{ + int i; + + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) + if (prottbl[i].protocol == protocol) { + (*prottbl[i].protrej)(unit); + return; + } + + syslog(LOG_WARNING, "Unrecognized Protocol-Reject for protocol 0x%x", + protocol); } /* - * quit - Clean up state and exit. + * quit - Clean up state and exit (with an error indication). */ void quit() { - die(0); + die(1); } /* @@ -630,7 +517,7 @@ void die(status) int status; { - cleanup(0, NULL); + cleanup(); syslog(LOG_INFO, "Exit."); exit(status); } @@ -639,43 +526,50 @@ die(status) * cleanup - restore anything which needs to be restored before we exit */ /* ARGSUSED */ -void -cleanup(status, arg) - int status; - caddr_t arg; +static void +cleanup() { - if (fd != 0) { - /* drop dtr to hang up */ - if (modem) - setdtr(fd, FALSE); + sys_cleanup(); - if (fcntl(fd, F_SETFL, initfdflags) < 0) - syslog(LOG_ERR, "fcntl(F_SETFL, fdflags): %m"); + if (fd >= 0) + close_fd(); - disestablish_ppp(); + if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) + syslog(LOG_WARNING, "unable to delete pid file: %m"); + pidfilename[0] = 0; - if (restore_term) { -#ifndef SGTTY - if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) - syslog(LOG_ERR, "tcsetattr: %m"); -#else - if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) - syslog(LOG_ERR, "ioctl(TIOCSETP): %m"); -#endif - } + if (lockflag && !default_device) + unlock(); +} - close(fd); - fd = 0; - } +/* + * close_fd - restore the terminal device and close it. + */ +static void +close_fd() +{ + disestablish_ppp(); - if (pidfilename[0] != 0 && unlink(pidfilename) < 0) - syslog(LOG_WARNING, "unable to unlink pid file: %m"); - pidfilename[0] = 0; + /* drop dtr to hang up */ + if (modem) + setdtr(fd, FALSE); + + restore_tty(); + + close(fd); + fd = -1; } -static struct callout *callout = NULL; /* Callout list */ -static struct timeval schedtime; /* Time last timeout was set */ +struct callout { + struct timeval c_time; /* time at which to call routine */ + caddr_t c_arg; /* argument to routine */ + void (*c_func)(); /* routine */ + struct callout *c_next; +}; + +static struct callout *callout = NULL; /* Callout list */ +static struct timeval timenow; /* Current time */ /* * timeout - Schedule a timeout. @@ -689,11 +583,10 @@ timeout(func, arg, time) caddr_t arg; int time; { - struct itimerval itv; - struct callout *newp, **oldpp; + struct callout *newp, *p, **pp; - MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.", - (int) func, (int) arg, time)); + MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.", + (long) func, (long) arg, time)); /* * Allocate timeout. @@ -704,40 +597,20 @@ timeout(func, arg, time) } newp->c_arg = arg; newp->c_func = func; + gettimeofday(&timenow, NULL); + newp->c_time.tv_sec = timenow.tv_sec + time; + newp->c_time.tv_usec = timenow.tv_usec; /* - * Find correct place to link it in and decrement its time by the - * amount of time used by preceding timeouts. + * Find correct place and link it in. */ - for (oldpp = &callout; - *oldpp && (*oldpp)->c_time <= time; - oldpp = &(*oldpp)->c_next) - time -= (*oldpp)->c_time; - newp->c_time = time; - newp->c_next = *oldpp; - if (*oldpp) - (*oldpp)->c_time -= time; - *oldpp = newp; - - /* - * If this is now the first callout then we have to set a new - * itimer. - */ - if (callout == newp) { - itv.it_interval.tv_sec = itv.it_interval.tv_usec = - itv.it_value.tv_usec = 0; - itv.it_value.tv_sec = callout->c_time; - MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds.", - itv.it_value.tv_sec)); - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m"); - die(1); - } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday: %m"); - die(1); - } - } + for (pp = &callout; (p = *pp); pp = &p->c_next) + if (newp->c_time.tv_sec < p->c_time.tv_sec + || (newp->c_time.tv_sec == p->c_time.tv_sec + && newp->c_time.tv_usec < p->c_time.tv_sec)) + break; + newp->c_next = p; + *pp = newp; } @@ -753,463 +626,389 @@ untimeout(func, arg) struct callout **copp, *freep; int reschedule = 0; - MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg)); + MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); /* - * If the first callout is unscheduled then we have to set a new - * itimer. + * Find first matching timeout and remove it from the list. */ - 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; + for (copp = &callout; (freep = *copp); copp = &freep->c_next) + if (freep->c_func == func && freep->c_arg == arg) { *copp = freep->c_next; - if (*copp) - (*copp)->c_time += freep->c_time; (void) free((char *) freep); break; } - - if (reschedule) { - itv.it_interval.tv_sec = itv.it_interval.tv_usec = - itv.it_value.tv_usec = 0; - itv.it_value.tv_sec = callout ? callout->c_time : 0; - MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds.", - itv.it_value.tv_sec)); - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m"); - die(1); - } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday: %m"); - die(1); - } - } } /* - * adjtimeout - Decrement the first timeout by the amount of time since - * it was scheduled. + * calltimeout - Call any timeout routines which are now due. */ -void -adjtimeout() +static void +calltimeout() { - struct timeval tv; - int timediff; - - if (callout == NULL) - return; - /* - * Make sure that the clock hasn't been warped dramatically. - * Account for recently expired, but blocked timer by adding - * small fudge factor. - */ - if (gettimeofday(&tv, NULL)) { - syslog(LOG_ERR, "gettimeofday: %m"); - die(1); + struct callout *p; + + while (callout != NULL) { + p = callout; + + if (gettimeofday(&timenow, NULL) < 0) { + syslog(LOG_ERR, "Failed to get time of day: %m"); + die(1); + } + if (!(p->c_time.tv_sec < timenow.tv_sec + || (p->c_time.tv_sec == timenow.tv_sec + && p->c_time.tv_usec <= timenow.tv_usec))) + break; /* no, it's not time yet */ + + callout = p->c_next; + (*p->c_func)(p->c_arg); + + free((char *) p); } - timediff = tv.tv_sec - schedtime.tv_sec; - if (timediff < 0 || - timediff > callout->c_time + 1) - return; - - callout->c_time -= timediff; /* OK, Adjust time */ } /* - * hup - Catch SIGHUP signal. - * - * Indicates that the physical layer has been disconnected. + * timeleft - return the length of time until the next timeout is due. */ -/*ARGSUSED*/ -static void -hup(sig, code, scp, addr) - int sig, code; - struct sigcontext *scp; - char *addr; +static struct timeval * +timeleft(tvp) + struct timeval *tvp; { - syslog(LOG_INFO, "Hangup (SIGHUP)"); + if (callout == NULL) + return NULL; + + gettimeofday(&timenow, NULL); + tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec; + tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec; + if (tvp->tv_usec < 0) { + tvp->tv_usec += 1000000; + tvp->tv_sec -= 1; + } + if (tvp->tv_sec < 0) + tvp->tv_sec = tvp->tv_usec = 0; - hungup = 1; /* they hung up on us! */ - persist = 0; /* don't try to restart */ - adjtimeout(); /* Adjust timeouts */ - lcp_lowerdown(0); /* Reset connection */ - quit(); /* and die */ + return tvp; } - + /* - * term - Catch SIGTERM signal. + * hup - Catch SIGHUP signal. * - * Indicates that we should initiate a graceful disconnect and exit. + * Indicates that the physical layer has been disconnected. + * We don't rely on this indication; if the user has sent this + * signal, we just take the link down. */ -/*ARGSUSED*/ static void -term(sig, code, scp, addr) - int sig, code; - struct sigcontext *scp; - char *addr; +hup(sig) + int sig; { - syslog(LOG_INFO, "Terminating link."); - persist = 0; /* don't try to restart */ - adjtimeout(); /* Adjust timeouts */ - lcp_close(0); /* Close connection */ + syslog(LOG_INFO, "Hangup (SIGHUP)"); + kill_link = 1; } /* - * intr - Catch SIGINT signal (DEL/^C). + * term - Catch SIGTERM signal and SIGINT signal (^C/del). * * Indicates that we should initiate a graceful disconnect and exit. */ /*ARGSUSED*/ static void -intr(sig, code, scp, addr) - int sig, code; - struct sigcontext *scp; - char *addr; +term(sig) + int sig; { - syslog(LOG_INFO, "Interrupt received: terminating link"); + syslog(LOG_INFO, "Terminating on signal %d.", sig); persist = 0; /* don't try to restart */ - adjtimeout(); /* Adjust timeouts */ - lcp_close(0); /* Close connection */ + kill_link = 1; } /* - * alrm - Catch SIGALRM signal. - * - * Indicates a timeout. + * chld - Catch SIGCHLD signal. + * Calls reap_kids to get status for any dead kids. */ -/*ARGSUSED*/ static void -alrm(sig, code, scp, addr) - int sig, code; - struct sigcontext *scp; - char *addr; +chld(sig) + int sig; { - 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 = 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); - } - } + reap_kids(); } /* - * io - Catch SIGIO signal. + * toggle_debug - Catch SIGUSR1 signal. * - * Indicates that incoming data is available. + * Toggle debug flag. */ /*ARGSUSED*/ static void -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; - - 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 */ - - len = read_packet(inpacket_buf); - if (len < 0) - return; - - if (len == 0) { - syslog(LOG_ERR, "End of file on fd!"); - die(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 != OPENED) { - MAINDEBUG((LOG_INFO, - "io(): Received non-LCP packet when LCP not open.")); - if (debug) - dumpbuffer(inpacket_buf, len + DLLHEADERLEN, LOG_INFO); - return; - } - - /* - * Upcall the proper protocol input routine. - */ - for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) - if (prottbl[i].protocol == protocol) { - (*prottbl[i].input)(0, p, len); - break; - } - - if (i == sizeof (prottbl) / sizeof (struct protent)) { - syslog(LOG_WARNING, "input: Unknown protocol (%x) received!", - protocol); - lcp_sprotrej(0, p - DLLHEADERLEN, len + DLLHEADERLEN); - } - } -} - -/* - * demuxprotrej - Demultiplex a Protocol-Reject. - */ -void -demuxprotrej(unit, protocol) - int unit; - u_short protocol; +toggle_debug(sig) + int sig; { - 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); + debug = !debug; + note_debug_level(); } /* - * incdebug - Catch SIGUSR1 signal. + * open_ccp - Catch SIGUSR2 signal. * - * Increment debug flag. + * Try to (re)negotiate compression. */ /*ARGSUSED*/ static void -incdebug(sig) +open_ccp(sig) int sig; { - syslog(LOG_INFO, "Debug turned ON, Level %d", debug); - setlogmask(LOG_UPTO(LOG_DEBUG)); - debug++; + open_ccp_flag = 1; } /* - * nodebug - Catch SIGUSR2 signal. - * - * Turn off debugging. + * bad_signal - We've caught a fatal signal. Clean up state and exit. */ -/*ARGSUSED*/ static void -nodebug(sig) +bad_signal(sig) int sig; { - setlogmask(LOG_UPTO(LOG_WARNING)); - debug = 0; + syslog(LOG_ERR, "Fatal signal %d", sig); + die(1); } /* - * set_up_connection - run a program to initialize the serial connector + * device_script - run a program to connect or disconnect the + * serial device. */ -int -set_up_connection(program, in, out) +static int +device_script(program, in, out) char *program; int in, out; { int pid; int status; - sigset_t mask; - - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &mask); + int errfd; pid = fork(); - + if (pid < 0) { - syslog(LOG_ERR, "fork: %m"); + syslog(LOG_ERR, "Failed to create child process: %m"); die(1); } - + if (pid == 0) { - setreuid(getuid(), getuid()); - setregid(getgid(), getgid()); - sigprocmask(SIG_SETMASK, &mask, NULL); dup2(in, 0); dup2(out, 1); + errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644); + if (errfd >= 0) + dup2(errfd, 2); + setuid(getuid()); + setgid(getgid()); execl("/bin/sh", "sh", "-c", program, (char *)0); syslog(LOG_ERR, "could not exec /bin/sh: %m"); _exit(99); /* NOTREACHED */ } - while (waitpid(pid, &status, 0) != pid) { + while (waitpid(pid, &status, 0) < 0) { if (errno == EINTR) continue; - syslog(LOG_ERR, "waiting for connection process: %m"); + syslog(LOG_ERR, "error waiting for (dis)connection process: %m"); die(1); } - sigprocmask(SIG_SETMASK, &mask, NULL); return (status == 0 ? 0 : -1); } /* - * Return user specified netmask. A value of zero means no netmask has - * been set. + * run-program - execute a program with given arguments, + * but don't wait for it. + * If the program can't be executed, logs an error unless + * must_exist is 0 and the program file doesn't exist. */ -/* ARGSUSED */ -u_long -GetMask(addr) - u_long addr; +int +run_program(prog, args, must_exist) + char *prog; + char **args; + int must_exist; { - return(netmask); + int pid; + char *nullenv[1]; + + pid = fork(); + if (pid == -1) { + syslog(LOG_ERR, "Failed to create child process for %s: %m", prog); + return -1; + } + if (pid == 0) { + int new_fd; + + /* Leave the current location */ + (void) setsid(); /* No controlling tty. */ + (void) umask (S_IRWXG|S_IRWXO); + (void) chdir ("/"); /* no current directory. */ + setuid(geteuid()); + setgid(getegid()); + + /* Ensure that nothing of our device environment is inherited. */ + close (0); + close (1); + close (2); + close (fd); /* tty interface to the ppp device */ + /* XXX should call sysdep cleanup procedure here */ + + /* Don't pass handles to the PPP device, even by accident. */ + new_fd = open (_PATH_DEVNULL, O_RDWR); + if (new_fd >= 0) { + if (new_fd != 0) { + dup2 (new_fd, 0); /* stdin <- /dev/null */ + close (new_fd); + } + dup2 (0, 1); /* stdout -> /dev/null */ + dup2 (0, 2); /* stderr -> /dev/null */ + } + +#ifdef BSD + /* Force the priority back to zero if pppd is running higher. */ + if (setpriority (PRIO_PROCESS, 0, 0) < 0) + syslog (LOG_WARNING, "can't reset priority to 0: %m"); +#endif + + /* SysV recommends a second fork at this point. */ + + /* run the program; give it a null environment */ + nullenv[0] = NULL; + execve(prog, args, nullenv); + if (must_exist || errno != ENOENT) + syslog(LOG_WARNING, "Can't execute %s: %m", prog); + _exit(-1); + } + MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid)); + ++n_children; + return 0; } + /* - * dumpbuffer - print contents of a buffer in hex to standard output. + * reap_kids - get status from any dead child processes, + * and log a message for abnormal terminations. */ -void -dumpbuffer(buffer, size, level) - unsigned char *buffer; - int size; - int level; +static void +reap_kids() { - register int i; - char line[256], *p; - - printf("%d bytes:\n", size); - while (size > 0) - { - p = line; - sprintf(p, "%08lx: ", buffer); - p += 10; - - for (i = 0; i < 8; i++, p += 3) - if (size - i <= 0) - sprintf(p, "xx "); - else - sprintf(p, "%02x ", buffer[i]); - - for (i = 0; i < 8; i++) - if (size - i <= 0) - *p++ = 'x'; - else - *p++ = (' ' <= buffer[i] && buffer[i] <= '~') ? - buffer[i] : '.'; - - *p++ = 0; - buffer += 8; - size -= 8; - -/* syslog(level, "%s\n", line); */ - printf("%s\n", line); - fflush(stdout); + int pid, status; + + if (n_children == 0) + return; + if ((pid = waitpid(-1, &status, WNOHANG)) == -1) { + if (errno != ECHILD) + syslog(LOG_ERR, "Error waiting for child process: %m"); + return; + } + if (pid > 0) { + --n_children; + if (WIFSIGNALED(status)) { + syslog(LOG_WARNING, "Child process %d terminated with signal %d", + pid, WTERMSIG(status)); + } } } /* - * setdtr - control the DTR line on the serial port. - * This is called from die(), so it shouldn't call die(). + * log_packet - format a packet and log it. + */ + +char line[256]; /* line to be logged accumulated here */ +char *linep; + +void +log_packet(p, len, prefix) + u_char *p; + int len; + char *prefix; +{ + strcpy(line, prefix); + linep = line + strlen(line); + format_packet(p, len, pr_log, NULL); + if (linep != line) + syslog(LOG_DEBUG, "%s", line); +} + +/* + * format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. */ -setdtr(fd, on) -int fd, on; +void +format_packet(p, len, printer, arg) + u_char *p; + int len; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + int i, n; + u_short proto; + u_char x; + + if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { + p += 2; + GETSHORT(proto, p); + len -= PPP_HDRLEN; + for (i = 0; i < N_PROTO; ++i) + if (proto == prottbl[i].protocol) + break; + if (i < N_PROTO) { + printer(arg, "[%s", prottbl[i].name); + n = (*prottbl[i].printpkt)(p, len, printer, arg); + printer(arg, "]"); + p += n; + len -= n; + } else { + printer(arg, "[proto=0x%x]", proto); + } + } + + for (; len > 0; --len) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } +} + +#ifdef __STDC__ +#include + +static void +pr_log(void *arg, char *fmt, ...) { - int modembits = TIOCM_DTR; + int n; + va_list pvar; + char buf[256]; + + va_start(pvar, fmt); + vsprintf(buf, fmt, pvar); + va_end(pvar); - ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); + n = strlen(buf); + if (linep + n + 1 > line + sizeof(line)) { + syslog(LOG_DEBUG, "%s", line); + linep = line; + } + strcpy(linep, buf); + linep += n; } +#else /* __STDC__ */ #include -char line[256]; -char *p; - -logf(level, fmt, va_alist) -int level; +static void +pr_log(arg, fmt, va_alist) +void *arg; char *fmt; va_dcl { + int n; va_list pvar; char buf[256]; @@ -1217,15 +1016,43 @@ va_dcl vsprintf(buf, fmt, pvar); va_end(pvar); - p = line + strlen(line); - strcat(p, buf); + n = strlen(buf); + if (linep + n + 1 > line + sizeof(line)) { + syslog(LOG_DEBUG, "%s", line); + linep = line; + } + strcpy(linep, buf); + linep += n; +} +#endif - if (buf[strlen(buf)-1] == '\n') { - syslog(level, "%s", line); - line[0] = 0; +/* + * print_string - print a readable representation of a string using + * printer. + */ +void +print_string(p, len, printer, arg) + char *p; + int len; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') + printer(arg, "%c", c); + else + printer(arg, "\\%.3o", c); } + printer(arg, "\""); } +/* + * novm - log an error message saying we ran out of memory, and die. + */ void novm(msg) char *msg;