main.c revision 1.9
1/*	$OpenBSD: main.c,v 1.9 1996/07/20 12:02:11 joshd Exp $	*/
2
3/*
4 * main.c - Point-to-Point Protocol main module
5 *
6 * Copyright (c) 1989 Carnegie Mellon University.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by Carnegie Mellon University.  The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22#ifndef lint
23static char rcsid[] = "$OpenBSD: main.c,v 1.9 1996/07/20 12:02:11 joshd Exp $";
24#endif
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include <signal.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <syslog.h>
34#include <netdb.h>
35#include <utmp.h>
36#include <pwd.h>
37#include <sys/param.h>
38#include <sys/types.h>
39#include <sys/wait.h>
40#include <sys/time.h>
41#include <sys/resource.h>
42#include <sys/stat.h>
43#include <sys/socket.h>
44#include <net/if.h>
45
46#include "pppd.h"
47#include "magic.h"
48#include "fsm.h"
49#include "lcp.h"
50#include "ipcp.h"
51#include "upap.h"
52#include "chap.h"
53#include "ccp.h"
54#include "pathnames.h"
55#include "patchlevel.h"
56
57#ifdef IPX_CHANGE
58#include "ipxcp.h"
59#endif /* IPX_CHANGE */
60
61/*
62 * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless
63 * /etc/ppp/options exists.
64 */
65#ifndef	REQ_SYSOPTIONS
66#define REQ_SYSOPTIONS	1
67#endif
68
69/* interface vars */
70char ifname[IFNAMSIZ];		/* Interface name */
71int ifunit;			/* Interface unit number */
72
73char *progname;			/* Name of this program */
74char hostname[MAXNAMELEN];	/* Our hostname */
75static char pidfilename[MAXPATHLEN];	/* name of pid file */
76static char default_devnam[MAXPATHLEN];	/* name of default device */
77static pid_t pid;		/* Our pid */
78static uid_t uid;		/* Our real user-id */
79
80int ttyfd = -1;			/* Serial port file descriptor */
81mode_t tty_mode = -1;           /* Original access permissions to tty */
82int baud_rate;                  /* Actual bits/second for serial device */
83int hungup;                     /* terminal has been hung up */
84
85
86int phase;			/* where the link is at */
87int kill_link;
88int open_ccp_flag;
89int redirect_stderr;          /* Connector's stderr should go to file */
90
91u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
92u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
93
94int hungup;			/* terminal has been hung up */
95static int n_children;		/* # child processes still running */
96
97int baud_rate;			/* Actual bits/second for serial device */
98
99static int locked;		/* lock() has succeeded */
100
101char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
102
103/* Prototypes for procedures local to this file. */
104
105static void cleanup __P((void));
106static void close_tty __P((void));
107static void get_input __P((void));
108static void connect_time_expired __P((caddr_t));
109static void calltimeout __P((void));
110static struct timeval *timeleft __P((struct timeval *));
111static void hup __P((int));
112static void term __P((int));
113static void chld __P((int));
114static void toggle_debug __P((int));
115static void open_ccp __P((int));
116static void bad_signal __P((int));
117static void holdoff_end __P((void *));
118static int device_script __P((char *, int, int));
119static void reap_kids __P((void));
120static void pr_log __P((void *, char *, ...));
121
122extern	char	*ttyname __P((int));
123extern	char	*getlogin __P((void));
124
125#ifdef ultrix
126#undef	O_NONBLOCK
127#define	O_NONBLOCK	O_NDELAY
128#endif
129
130#ifdef PRIMITIVE_SYSLOG
131#define setlogmask(x)
132#endif
133
134/*
135 * PPP Data Link Layer "protocol" table.
136 * One entry per supported protocol.
137 * The last entry must be NULL.
138 */
139struct protent *protocols[] = {
140    &lcp_protent,
141    &pap_protent,
142    &chap_protent,
143    &ipcp_protent,
144    &ccp_protent,
145#ifdef IPX_CHANGE
146    &ipxcp_protent,
147#endif
148    NULL
149};
150
151int
152main(argc, argv)
153    int argc;
154    char *argv[];
155{
156    int i, nonblock, fdflags;
157    struct sigaction sa;
158    FILE *pidfile;
159    char *p;
160    struct passwd *pw;
161    struct timeval timo;
162    sigset_t mask;
163    struct protent *protp;
164    struct stat statbuf;
165
166    phase = PHASE_INITIALIZE;
167    p = ttyname(0);
168    if (p)
169	strcpy(devnam, p);
170    strcpy(default_devnam, devnam);
171
172    /* Initialize syslog facilities */
173#ifdef PRIMITIVE_SYSLOG
174    openlog("pppd", LOG_PID);
175#else
176    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
177    setlogmask(LOG_UPTO(LOG_INFO));
178#endif
179
180    if (gethostname(hostname, MAXNAMELEN) < 0 ) {
181        syslog(LOG_ERR, "couldn't get hostname: %m");
182	die(1);
183    }
184    hostname[MAXNAMELEN-1] = 0;
185
186    uid = getuid();
187
188    /*
189     * Initialize to the standard option set, then parse, in order,
190     * the system options file, the user's options file,
191     * the tty's options file, and the command line arguments.
192     */
193    for (i = 0; (protp = protocols[i]) != NULL; ++i)
194        (*protp->init)(0);
195
196    progname = *argv;
197
198    if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0)
199        || !options_from_user())
200        exit(1);
201    scan_args(argc-1, argv+1);  /* look for tty name on command line */
202    if (!options_for_tty()
203        || !parse_args(argc-1, argv+1))
204	exit(1);
205
206    if (!ppp_available()) {
207	fprintf(stderr, no_ppp_msg);
208	exit(1);
209    }
210
211    /*
212     * Check that the options given are valid and consistent.
213     */
214    sys_check_options();
215    auth_check_options();
216    for (i = 0; (protp = protocols[i]) != NULL; ++i)
217	if (protp->check_options != NULL)
218	    (*protp->check_options)();
219    if (demand && connector == 0) {
220	fprintf(stderr, "%s: connect script required for demand-dialling\n",
221		progname);
222	exit(1);
223    }
224
225    /*
226     * If the user has specified the default device name explicitly,
227     * pretend they hadn't.
228     */
229    if (!default_device && strcmp(devnam, default_devnam) == 0)
230	default_device = 1;
231    redirect_stderr = !nodetach || default_device;
232
233
234    /*
235     * Initialize system-dependent stuff and magic number package.
236     */
237    sys_init();
238    magic_init();
239    if (debug)
240      setlogmask(LOG_UPTO(LOG_DEBUG));
241
242
243    /*
244     * Detach ourselves from the terminal, if required,
245     * and identify who is running us.
246     */
247    if (!default_device && !nodetach && daemon(0, 0) < 0) {
248	perror("Couldn't detach from controlling terminal");
249	exit(1);
250    }
251    pid = getpid();
252    p = getlogin();
253    if (p == NULL) {
254	pw = getpwuid(uid);
255	if (pw != NULL && pw->pw_name != NULL)
256	    p = pw->pw_name;
257	else
258	    p = "(unknown)";
259    }
260    syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d",
261	   VERSION, PATCHLEVEL, p, uid);
262
263    /*
264     * Compute mask of all interesting signals and install signal handlers
265     * for each.  Only one signal handler may be active at a time.  Therefore,
266     * all other signals should be masked when any handler is executing.
267     */
268    sigemptyset(&mask);
269    sigaddset(&mask, SIGHUP);
270    sigaddset(&mask, SIGINT);
271    sigaddset(&mask, SIGTERM);
272    sigaddset(&mask, SIGCHLD);
273
274#define SIGNAL(s, handler)	{ \
275	sa.sa_handler = handler; \
276	if (sigaction(s, &sa, NULL) < 0) { \
277	    syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
278	    die(1); \
279	} \
280    }
281
282    sa.sa_mask = mask;
283    sa.sa_flags = 0;
284    SIGNAL(SIGHUP, hup);		/* Hangup */
285    SIGNAL(SIGINT, term);		/* Interrupt */
286    SIGNAL(SIGTERM, term);		/* Terminate */
287    SIGNAL(SIGCHLD, chld);
288
289    SIGNAL(SIGUSR1, toggle_debug);	/* Toggle debug flag */
290    SIGNAL(SIGUSR2, open_ccp);		/* Reopen CCP */
291
292    /*
293     * Install a handler for other signals which would otherwise
294     * cause pppd to exit without cleaning up.
295     */
296    SIGNAL(SIGABRT, bad_signal);
297    SIGNAL(SIGALRM, bad_signal);
298    SIGNAL(SIGFPE, bad_signal);
299    SIGNAL(SIGILL, bad_signal);
300    SIGNAL(SIGPIPE, bad_signal);
301    SIGNAL(SIGQUIT, bad_signal);
302    SIGNAL(SIGSEGV, bad_signal);
303#ifdef SIGBUS
304    SIGNAL(SIGBUS, bad_signal);
305#endif
306#ifdef SIGEMT
307    SIGNAL(SIGEMT, bad_signal);
308#endif
309#ifdef SIGPOLL
310    SIGNAL(SIGPOLL, bad_signal);
311#endif
312#ifdef SIGPROF
313    SIGNAL(SIGPROF, bad_signal);
314#endif
315#ifdef SIGSYS
316    SIGNAL(SIGSYS, bad_signal);
317#endif
318#ifdef SIGTRAP
319    SIGNAL(SIGTRAP, bad_signal);
320#endif
321#ifdef SIGVTALRM
322    SIGNAL(SIGVTALRM, bad_signal);
323#endif
324#ifdef SIGXCPU
325    SIGNAL(SIGXCPU, bad_signal);
326#endif
327#ifdef SIGXFSZ
328    SIGNAL(SIGXFSZ, bad_signal);
329#endif
330
331    /*
332     * Apparently we can get a SIGPIPE when we call syslog, if
333     * syslogd has died and been restarted.  Ignoring it seems
334     * be sufficient.
335     */
336    signal(SIGPIPE, SIG_IGN);
337
338    /*
339     * If we're doing dial-on-demand, set up the interface now.
340     */
341    if (demand) {
342	/*
343	 * Open the loopback channel and set it up to be the ppp interface.
344	 */
345	open_ppp_loopback();
346
347	syslog(LOG_INFO, "Using interface ppp%d", ifunit);
348	(void) sprintf(ifname, "ppp%d", ifunit);
349
350	/* write pid to file */
351	(void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
352	if ((pidfile = fopen(pidfilename, "w")) != NULL) {
353	    fprintf(pidfile, "%d\n", pid);
354	    (void) fclose(pidfile);
355	} else {
356	    syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename);
357	    pidfilename[0] = 0;
358	}
359
360	/*
361	 * Configure the interface and mark it up, etc.
362	 */
363	demand_conf();
364    }
365
366    for (;;) {
367
368	if (demand) {
369	    /*
370	     * Don't do anything until we see some activity.
371	     */
372	    phase = PHASE_DORMANT;
373	    kill_link = 0;
374	    demand_unblock();
375	    for (;;) {
376		wait_loop_output(timeleft(&timo));
377		calltimeout();
378		if (kill_link) {
379		    if (!persist)
380			die(0);
381		    kill_link = 0;
382		}
383		if (get_loop_output())
384		    break;
385		reap_kids();
386	    }
387
388	    /*
389	     * Now we want to bring up the link.
390	     */
391	    demand_block();
392	    syslog(LOG_INFO, "Starting link");
393	}
394
395	/*
396	 * Lock the device if we've been asked to.
397	 */
398	if (lockflag && !default_device) {
399	    if (lock(devnam) < 0)
400		goto fail;
401	    locked = 1;
402	}
403
404	/*
405	 * Open the serial device and set it up to be the ppp interface.
406	 * If we're dialling out, or we don't want to use the modem lines,
407	 * we open it in non-blocking mode, but then we need to clear
408	 * the non-blocking I/O bit.
409	 */
410	nonblock = (connector || !modem)? O_NONBLOCK: 0;
411	if ((ttyfd = open(devnam, nonblock | O_RDWR, 0)) < 0) {
412	    syslog(LOG_ERR, "Failed to open %s: %m", devnam);
413	    goto fail;
414	}
415	if (nonblock) {
416	    if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
417		|| fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
418		syslog(LOG_WARNING,
419		       "Couldn't reset non-blocking mode on device: %m");
420	}
421	hungup = 0;
422	kill_link = 0;
423
424        /*
425         * Do the equivalent of `mesg n' to stop broadcast messages.
426         */
427        if (fstat(ttyfd, &statbuf) < 0
428            || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
429            syslog(LOG_WARNING,
430                   "Couldn't restrict write permissions to %s: %m", devnam);
431        } else
432            tty_mode = statbuf.st_mode;
433
434	/* run connection script */
435	if (connector && connector[0]) {
436	    MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
437
438	    /* set line speed, flow control, etc.; set CLOCAL for now */
439	    set_up_tty(ttyfd, 1);
440
441	    /* drop dtr to hang up in case modem is off hook */
442	    if (!default_device && modem) {
443		setdtr(ttyfd, FALSE);
444		sleep(1);
445		setdtr(ttyfd, TRUE);
446	    }
447
448	    if (device_script(connector, ttyfd, ttyfd) < 0) {
449		syslog(LOG_ERR, "Connect script failed");
450		setdtr(ttyfd, FALSE);
451		goto fail;
452	    }
453
454	    syslog(LOG_INFO, "Serial connection established.");
455	    sleep(1);		/* give it time to set up its terminal */
456	}
457
458	/* set line speed, flow control, etc.; clear CLOCAL if modem option */
459	set_up_tty(ttyfd, 0);
460
461	/* run welcome script, if any */
462	if (welcomer && welcomer[0]) {
463	    if (device_script(welcomer, ttyfd, ttyfd) < 0)
464		syslog(LOG_WARNING, "Welcome script failed");
465	}
466
467	/* set up the serial device as a ppp interface */
468	establish_ppp(ttyfd);
469
470	if (!demand) {
471
472	    syslog(LOG_INFO, "Using interface ppp%d", ifunit);
473	    (void) sprintf(ifname, "ppp%d", ifunit);
474
475	    /* write pid to file */
476	    (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
477	    if ((pidfile = fopen(pidfilename, "w")) != NULL) {
478		fprintf(pidfile, "%d\n", pid);
479		(void) fclose(pidfile);
480	    } else {
481		syslog(LOG_ERR, "Failed to create pid file %s: %m",
482		       pidfilename);
483		pidfilename[0] = 0;
484	    }
485	}
486
487	/*
488	 * Set a timeout to close the connection once the maximum
489	 * connect time has expired.
490	 */
491	if (maxconnect > 0)
492	    TIMEOUT(connect_time_expired, 0, maxconnect);
493
494	/*
495	 * Start opening the connection and wait for
496	 * incoming events (reply, timeout, etc.).
497	 */
498	syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
499	lcp_lowerup(0);
500	lcp_open(0);		/* Start protocol */
501	for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
502	    wait_input(timeleft(&timo));
503	    calltimeout();
504	    get_input();
505	    if (kill_link) {
506		lcp_close(0, "User request");
507		phase = PHASE_TERMINATE;
508		kill_link = 0;
509	    }
510	    if (open_ccp_flag) {
511		if (phase == PHASE_NETWORK) {
512		    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
513                    (*ccp_protent.open)(0);
514		}
515		open_ccp_flag = 0;
516	    }
517	    reap_kids();	/* Don't leave dead kids lying around */
518	}
519
520	/*
521	 * If we may want to bring the link up again, transfer
522	 * the ppp unit back to the loopback.  Set the
523	 * real serial device back to its normal mode of operation.
524	 */
525	clean_check();
526	if (demand)
527	    restore_loop();
528	disestablish_ppp(ttyfd);
529
530	/*
531	 * Run disconnector script, if requested.
532	 * XXX we may not be able to do this if the line has hung up!
533	 */
534	if (disconnector && !hungup) {
535	    set_up_tty(ttyfd, 1);
536	    if (device_script(disconnector, ttyfd, ttyfd) < 0) {
537		syslog(LOG_WARNING, "disconnect script failed");
538	    } else {
539		syslog(LOG_INFO, "Serial link disconnected.");
540	    }
541	}
542
543    fail:
544	close_tty();
545	if (locked) {
546	    unlock();
547	    locked = 0;
548	}
549
550	if (!demand) {
551            if (pidfilename[0] != 0
552                && unlink(pidfilename) < 0 && errno != ENOENT)
553		syslog(LOG_WARNING, "unable to delete pid file: %m");
554	    pidfilename[0] = 0;
555	}
556
557	if (!persist)
558	    break;
559
560	if (demand)
561	    demand_discard();
562	if (holdoff > 0) {
563	    phase = PHASE_HOLDOFF;
564	    TIMEOUT(holdoff_end, NULL, holdoff);
565	    do {
566		wait_time(timeleft(&timo));
567		calltimeout();
568		if (kill_link) {
569		    if (!persist)
570			die(0);
571		    kill_link = 0;
572		    phase = PHASE_DORMANT; /* allow signal to end holdoff */
573		}
574		reap_kids();
575	    } while (phase == PHASE_HOLDOFF);
576	}
577    }
578
579    die(0);
580}
581
582/*
583 * holdoff_end - called via a timeout when the holdoff period ends.
584 */
585static void
586holdoff_end(arg)
587    void *arg;
588{
589    phase = PHASE_DORMANT;
590}
591
592/*
593 * get_input - called when incoming data is available.
594 */
595static void
596get_input()
597{
598    int len, i;
599    u_char *p;
600    u_short protocol;
601    struct protent *protp;
602
603    p = inpacket_buf;	/* point to beginning of packet buffer */
604
605    len = read_packet(inpacket_buf);
606    if (len < 0)
607	return;
608
609    if (len == 0) {
610	syslog(LOG_NOTICE, "Modem hangup");
611	hungup = 1;
612	lcp_lowerdown(0);	/* serial link is no longer available */
613	link_terminated(0);
614	return;
615    }
616
617    if (debug /*&& (debugflags & DBG_INPACKET)*/)
618	log_packet(p, len, "rcvd ");
619
620    if (len < PPP_HDRLEN) {
621	MAINDEBUG((LOG_INFO, "io(): Received short packet."));
622	return;
623    }
624
625    p += 2;				/* Skip address and control */
626    GETSHORT(protocol, p);
627    len -= PPP_HDRLEN;
628
629    /*
630     * Toss all non-LCP packets unless LCP is OPEN.
631     */
632    if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
633	MAINDEBUG((LOG_INFO,
634		   "io(): Received non-LCP packet when LCP not open."));
635	return;
636    }
637
638    /*
639     * Upcall the proper protocol input routine.
640     */
641    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
642	if (protp->protocol == protocol && protp->enabled_flag) {
643	    (*protp->input)(0, p, len);
644	    return;
645	}
646        if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
647	    && protp->datainput != NULL) {
648	    (*protp->datainput)(0, p, len);
649	    return;
650	}
651    }
652
653    if (debug)
654    	syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
655    lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
656}
657
658
659/*
660 * quit - Clean up state and exit (with an error indication).
661 */
662void
663quit()
664{
665    die(1);
666}
667
668/*
669 * die - like quit, except we can specify an exit status.
670 */
671void
672die(status)
673    int status;
674{
675    cleanup();
676    syslog(LOG_INFO, "Exit.");
677    exit(status);
678}
679
680/*
681 * connect_time_expired - log a message and close the connection.
682 */
683static void
684connect_time_expired(arg)
685    caddr_t arg;
686{
687    syslog(LOG_INFO, "Connect time expired");
688
689    phase = PHASE_TERMINATE;
690    lcp_close(0, "Connect time expired");	/* Close connection */
691}
692
693/*
694 * cleanup - restore anything which needs to be restored before we exit
695 */
696/* ARGSUSED */
697static void
698cleanup()
699{
700    sys_cleanup();
701
702    if (ttyfd >= 0)
703	close_tty();
704
705    if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT)
706	syslog(LOG_WARNING, "unable to delete pid file: %m");
707    pidfilename[0] = 0;
708
709    if (locked)
710	unlock();
711}
712
713/*
714 * close_tty - restore the terminal device and close it.
715 */
716static void
717close_tty()
718{
719    disestablish_ppp(ttyfd);
720
721    /* drop dtr to hang up */
722    if (modem) {
723	setdtr(ttyfd, FALSE);
724	/*
725	 * This sleep is in case the serial port has CLOCAL set by default,
726	 * and consequently will reassert DTR when we close the device.
727	 */
728	sleep(1);
729    }
730
731    restore_tty(ttyfd);
732
733    if (tty_mode != (mode_t) -1)
734      chmod(devnam, tty_mode);
735
736    close(ttyfd);
737    ttyfd = -1;
738}
739
740
741struct	callout {
742    struct timeval	c_time;		/* time at which to call routine */
743    caddr_t		c_arg;		/* argument to routine */
744    void		(*c_func)();	/* routine */
745    struct		callout *c_next;
746};
747
748static struct callout *callout = NULL;	/* Callout list */
749static struct timeval timenow;		/* Current time */
750
751/*
752 * timeout - Schedule a timeout.
753 *
754 * Note that this timeout takes the number of seconds, NOT hz (as in
755 * the kernel).
756 */
757void
758timeout(func, arg, time)
759    void (*func)();
760    caddr_t arg;
761    int time;
762{
763    struct callout *newp, *p, **pp;
764
765    MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
766	       (long) func, (long) arg, time));
767
768    /*
769     * Allocate timeout.
770     */
771    if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
772	syslog(LOG_ERR, "Out of memory in timeout()!");
773	die(1);
774    }
775    newp->c_arg = arg;
776    newp->c_func = func;
777    gettimeofday(&timenow, NULL);
778    newp->c_time.tv_sec = timenow.tv_sec + time;
779    newp->c_time.tv_usec = timenow.tv_usec;
780
781    /*
782     * Find correct place and link it in.
783     */
784    for (pp = &callout; (p = *pp); pp = &p->c_next)
785	if (newp->c_time.tv_sec < p->c_time.tv_sec
786	    || (newp->c_time.tv_sec == p->c_time.tv_sec
787		&& newp->c_time.tv_usec < p->c_time.tv_sec))
788	    break;
789    newp->c_next = p;
790    *pp = newp;
791}
792
793
794/*
795 * untimeout - Unschedule a timeout.
796 */
797void
798untimeout(func, arg)
799    void (*func)();
800    caddr_t arg;
801{
802    struct callout **copp, *freep;
803
804    MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));
805
806    /*
807     * Find first matching timeout and remove it from the list.
808     */
809    for (copp = &callout; (freep = *copp); copp = &freep->c_next)
810	if (freep->c_func == func && freep->c_arg == arg) {
811	    *copp = freep->c_next;
812	    (void) free((char *) freep);
813	    break;
814	}
815}
816
817
818/*
819 * calltimeout - Call any timeout routines which are now due.
820 */
821static void
822calltimeout()
823{
824    struct callout *p;
825
826    while (callout != NULL) {
827	p = callout;
828
829	if (gettimeofday(&timenow, NULL) < 0) {
830	    syslog(LOG_ERR, "Failed to get time of day: %m");
831	    die(1);
832	}
833	if (!(p->c_time.tv_sec < timenow.tv_sec
834	      || (p->c_time.tv_sec == timenow.tv_sec
835		  && p->c_time.tv_usec <= timenow.tv_usec)))
836	    break;		/* no, it's not time yet */
837
838	callout = p->c_next;
839	(*p->c_func)(p->c_arg);
840
841	free((char *) p);
842    }
843}
844
845
846/*
847 * timeleft - return the length of time until the next timeout is due.
848 */
849static struct timeval *
850timeleft(tvp)
851    struct timeval *tvp;
852{
853    if (callout == NULL)
854	return NULL;
855
856    gettimeofday(&timenow, NULL);
857    tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
858    tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
859    if (tvp->tv_usec < 0) {
860	tvp->tv_usec += 1000000;
861	tvp->tv_sec -= 1;
862    }
863    if (tvp->tv_sec < 0)
864	tvp->tv_sec = tvp->tv_usec = 0;
865
866    return tvp;
867}
868
869
870/*
871 * hup - Catch SIGHUP signal.
872 *
873 * Indicates that the physical layer has been disconnected.
874 * We don't rely on this indication; if the user has sent this
875 * signal, we just take the link down.
876 */
877static void
878hup(sig)
879    int sig;
880{
881    syslog(LOG_INFO, "Hangup (SIGHUP)");
882    kill_link = 1;
883}
884
885
886/*
887 * term - Catch SIGTERM signal and SIGINT signal (^C/del).
888 *
889 * Indicates that we should initiate a graceful disconnect and exit.
890 */
891/*ARGSUSED*/
892static void
893term(sig)
894    int sig;
895{
896    syslog(LOG_INFO, "Terminating on signal %d.", sig);
897    persist = 0;		/* don't try to restart */
898    kill_link = 1;
899}
900
901
902/*
903 * chld - Catch SIGCHLD signal.
904 * Calls reap_kids to get status for any dead kids.
905 */
906static void
907chld(sig)
908    int sig;
909{
910    reap_kids();
911}
912
913
914/*
915 * toggle_debug - Catch SIGUSR1 signal.
916 *
917 * Toggle debug flag.
918 */
919/*ARGSUSED*/
920static void
921toggle_debug(sig)
922    int sig;
923{
924    debug = !debug;
925    if (debug) {
926      setlogmask(LOG_UPTO(LOG_DEBUG));
927    } else {
928      setlogmask(LOG_UPTO(LOG_WARNING));
929    }
930}
931
932
933/*
934 * open_ccp - Catch SIGUSR2 signal.
935 *
936 * Try to (re)negotiate compression.
937 */
938/*ARGSUSED*/
939static void
940open_ccp(sig)
941    int sig;
942{
943    open_ccp_flag = 1;
944}
945
946
947/*
948 * bad_signal - We've caught a fatal signal.  Clean up state and exit.
949 */
950static void
951bad_signal(sig)
952    int sig;
953{
954    syslog(LOG_ERR, "Fatal signal %d", sig);
955    die(1);
956}
957
958
959/*
960 * device_script - run a program to connect or disconnect the
961 * serial device.
962 */
963static int
964device_script(program, in, out)
965    char *program;
966    int in, out;
967{
968    int pid;
969    int status;
970    int errfd;
971
972    pid = fork();
973
974    if (pid < 0) {
975	syslog(LOG_ERR, "Failed to create child process: %m");
976	die(1);
977    }
978
979    if (pid == 0) {
980	sys_close();
981        closelog();
982        if (in == out) {
983            if (in != 0) {
984                dup2(in, 0);
985                close(in);
986            }
987            dup2(0, 1);
988        } else {
989            if (out == 0)
990                out = dup(out);
991            if (in != 0) {
992                dup2(in, 0);
993                close(in);
994            }
995            if (out != 1) {
996	        dup2(out, 1);
997                close(out);
998            }
999        }
1000        if (redirect_stderr) {
1001            close(2);
1002            errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644);
1003            if (errfd >= 0 && errfd != 2) {
1004	        dup2(errfd, 2);
1005                close(errfd);
1006            }
1007        }
1008	setuid(getuid());
1009	setgid(getgid());
1010	execl("/bin/sh", "sh", "-c", program, (char *)0);
1011	syslog(LOG_ERR, "could not exec /bin/sh: %m");
1012	_exit(99);
1013	/* NOTREACHED */
1014    }
1015
1016    while (waitpid(pid, &status, 0) < 0) {
1017	if (errno == EINTR)
1018	    continue;
1019	syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
1020	die(1);
1021    }
1022
1023    return (status == 0 ? 0 : -1);
1024}
1025
1026
1027/*
1028 * run-program - execute a program with given arguments,
1029 * but don't wait for it.
1030 * If the program can't be executed, logs an error unless
1031 * must_exist is 0 and the program file doesn't exist.
1032 */
1033int
1034run_program(prog, args, must_exist)
1035    char *prog;
1036    char **args;
1037    int must_exist;
1038{
1039    int pid;
1040    char *nullenv[1];
1041
1042
1043    pid = fork();
1044    if (pid == -1) {
1045	syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
1046	return -1;
1047    }
1048    if (pid == 0) {
1049	int new_fd;
1050
1051	/* Leave the current location */
1052	(void) setsid();    /* No controlling tty. */
1053	(void) umask (S_IRWXG|S_IRWXO);
1054	(void) chdir ("/"); /* no current directory. */
1055	setuid(geteuid());
1056	setgid(getegid());
1057
1058	/* Ensure that nothing of our device environment is inherited. */
1059	sys_close();
1060        closelog();
1061	close (0);
1062	close (1);
1063	close (2);
1064	close (ttyfd);  /* tty interface to the ppp device */
1065
1066        /* Don't pass handles to the PPP device, even by accident. */
1067	new_fd = open (_PATH_DEVNULL, O_RDWR);
1068	if (new_fd >= 0) {
1069	    if (new_fd != 0) {
1070	        dup2  (new_fd, 0); /* stdin <- /dev/null */
1071		close (new_fd);
1072	    }
1073	    dup2 (0, 1); /* stdout -> /dev/null */
1074	    dup2 (0, 2); /* stderr -> /dev/null */
1075	}
1076
1077#ifdef BSD
1078	/* Force the priority back to zero if pppd is running higher. */
1079	if (setpriority (PRIO_PROCESS, 0, 0) < 0)
1080	    syslog (LOG_WARNING, "can't reset priority to 0: %m");
1081#endif
1082
1083	/* SysV recommends a second fork at this point. */
1084
1085        /* run the program; give it a null environment */
1086        nullenv[0] = NULL;
1087        execve(prog, args, nullenv);
1088	if (must_exist || errno != ENOENT)
1089	    syslog(LOG_WARNING, "Can't execute %s: %m", prog);
1090	_exit(-1);
1091    }
1092    MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
1093    ++n_children;
1094    return 0;
1095}
1096
1097
1098/*
1099 * reap_kids - get status from any dead child processes,
1100 * and log a message for abnormal terminations.
1101 */
1102static void
1103reap_kids()
1104{
1105    int pid, status;
1106
1107    if (n_children == 0)
1108	return;
1109    if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
1110	if (errno != ECHILD)
1111	    syslog(LOG_ERR, "Error waiting for child process: %m");
1112	return;
1113    }
1114    if (pid > 0) {
1115	--n_children;
1116	if (WIFSIGNALED(status)) {
1117	    syslog(LOG_WARNING, "Child process %d terminated with signal %d",
1118		   pid, WTERMSIG(status));
1119	}
1120    }
1121}
1122
1123
1124/*
1125 * log_packet - format a packet and log it.
1126 */
1127
1128char line[256];			/* line to be logged accumulated here */
1129char *linep;
1130
1131void
1132log_packet(p, len, prefix)
1133    u_char *p;
1134    int len;
1135    char *prefix;
1136{
1137    strcpy(line, prefix);
1138    linep = line + strlen(line);
1139    format_packet(p, len, pr_log, NULL);
1140    if (linep != line)
1141	syslog(LOG_DEBUG, "%s", line);
1142}
1143
1144/*
1145 * format_packet - make a readable representation of a packet,
1146 * calling `printer(arg, format, ...)' to output it.
1147 */
1148void
1149format_packet(p, len, printer, arg)
1150    u_char *p;
1151    int len;
1152    void (*printer) __P((void *, char *, ...));
1153    void *arg;
1154{
1155    int i, n;
1156    u_short proto;
1157    u_char x;
1158    struct protent *protp;
1159
1160    if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
1161	p += 2;
1162	GETSHORT(proto, p);
1163	len -= PPP_HDRLEN;
1164	for (i = 0; (protp = protocols[i]) != NULL; ++i)
1165	    if (proto == protp->protocol)
1166		break;
1167	if (protp != NULL) {
1168	    printer(arg, "[%s", protp->name);
1169	    n = (*protp->printpkt)(p, len, printer, arg);
1170	    printer(arg, "]");
1171	    p += n;
1172	    len -= n;
1173	} else {
1174	    printer(arg, "[proto=0x%x]", proto);
1175	}
1176    }
1177
1178    for (; len > 0; --len) {
1179	GETCHAR(x, p);
1180	printer(arg, " %.2x", x);
1181    }
1182}
1183
1184static void
1185pr_log __V((void *arg, char *fmt, ...))
1186{
1187    int n;
1188    va_list pvar;
1189    char buf[256];
1190
1191#if __STDC__
1192    va_start(pvar, fmt);
1193#else
1194    void *arg;
1195    char *fmt;
1196    va_start(pvar);
1197    arg = va_arg(pvar, void *);
1198    fmt = va_arg(pvar, char *);
1199#endif
1200
1201    vsprintf(buf, fmt, pvar);
1202    va_end(pvar);
1203
1204    n = strlen(buf);
1205    if (linep + n + 1 > line + sizeof(line)) {
1206	syslog(LOG_DEBUG, "%s", line);
1207	linep = line;
1208    }
1209    strcpy(linep, buf);
1210    linep += n;
1211}
1212
1213/*
1214 * print_string - print a readable representation of a string using
1215 * printer.
1216 */
1217void
1218print_string(p, len, printer, arg)
1219    char *p;
1220    int len;
1221    void (*printer) __P((void *, char *, ...));
1222    void *arg;
1223{
1224    int c;
1225
1226    printer(arg, "\"");
1227    for (; len > 0; --len) {
1228	c = *p++;
1229        if (' ' <= c && c <= '~') {
1230            if (c == '\\' || c == '"')
1231                printer(arg, "\\");
1232	    printer(arg, "%c", c);
1233        } else {
1234            switch (c) {
1235            case '\n':
1236                printer(arg, "\\n");
1237                break;
1238            case '\r':
1239                printer(arg, "\\r");
1240                break;
1241            case '\t':
1242                printer(arg, "\\t");
1243                break;
1244            default:
1245	        printer(arg, "\\%.3o", c);
1246            }
1247      }
1248    }
1249
1250    printer(arg, "\"");
1251}
1252
1253/*
1254 * novm - log an error message saying we ran out of memory, and die.
1255 */
1256void
1257novm(msg)
1258    char *msg;
1259{
1260    syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
1261    die(1);
1262}
1263
1264/*
1265 * fmtmsg - format a message into a buffer.  Like sprintf except we
1266 * also specify the length of the output buffer, and we handle
1267 * %r (recursive format), %m (error message) and %I (IP address) formats.
1268 * Doesn't do floating-point formats.
1269 * Returns the number of chars put into buf.
1270 */
1271int
1272fmtmsg __V((char *buf, int buflen, char *fmt, ...))
1273{
1274    va_list args;
1275    int n;
1276
1277#if __STDC__
1278    va_start(args, fmt);
1279#else
1280    char *buf;
1281    int buflen;
1282    char *fmt;
1283    va_start(args);
1284    buf = va_arg(args, char *);
1285    buflen = va_arg(args, int);
1286    fmt = va_arg(args, char *);
1287#endif
1288    n = vfmtmsg(buf, buflen, fmt, args);
1289    va_end(args);
1290    return n;
1291}
1292
1293/*
1294 * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
1295 */
1296#define OUTCHAR(c)      (buflen > 0? (--buflen, *buf++ = (c)): 0)
1297
1298int
1299vfmtmsg(char *buf, int buflen, char *fmt, va_list args)
1300{
1301    int c, i, n;
1302    int width, prec, fillch;
1303    int base, len, neg, quoted;
1304    unsigned long val;
1305    char *str, *f, *buf0;
1306    unsigned char *p;
1307    va_list a;
1308    char num[32];
1309    time_t t;
1310    static char hexchars[16] = "0123456789abcdef";
1311
1312    buf0 = buf;
1313    --buflen;
1314    while (buflen > 0) {
1315        for (f = fmt; *f != '%' && *f != 0; ++f)
1316            ;
1317        if (f > fmt) {
1318            len = f - fmt;
1319            if (len > buflen)
1320                len = buflen;
1321            memcpy(buf, fmt, len);
1322            buf += len;
1323            buflen -= len;
1324            fmt = f;
1325        }
1326        if (*fmt == 0)
1327            break;
1328        c = *++fmt;
1329        width = prec = 0;
1330        fillch = ' ';
1331        if (c == '0') {
1332            fillch = '0';
1333            c = *++fmt;
1334        }
1335        if (c == '*') {
1336            width = va_arg(args, int);
1337            c = *++fmt;
1338        } else {
1339            while (isdigit(c)) {
1340                width = width * 10 + c - '0';
1341                c = *++fmt;
1342            }
1343        }
1344        if (c == '.') {
1345            c = *++fmt;
1346            if (c == '*') {
1347                prec = va_arg(args, int);
1348                c = *++fmt;
1349            } else {
1350                while (isdigit(c)) {
1351                    prec = prec * 10 + c - '0';
1352                    c = *++fmt;
1353                }
1354            }
1355        }
1356        str = 0;
1357        base = 0;
1358        neg = 0;
1359        ++fmt;
1360        switch (c) {
1361        case 'd':
1362            i = va_arg(args, int);
1363            if (i < 0) {
1364                neg = 1;
1365                val = -i;
1366            } else
1367                val = i;
1368            base = 10;
1369            break;
1370        case 'o':
1371            val = va_arg(args, unsigned int);
1372            base = 8;
1373            break;
1374        case 'x':
1375            val = va_arg(args, unsigned int);
1376            base = 16;
1377            break;
1378        case 'p':
1379            val = (unsigned long) va_arg(args, void *);
1380            base = 16;
1381            neg = 2;
1382            break;
1383        case 's':
1384            str = va_arg(args, char *);
1385            break;
1386        case 'c':
1387            num[0] = va_arg(args, int);
1388            num[1] = 0;
1389            str = num;
1390            break;
1391        case 'm':
1392            str = strerror(errno);
1393            break;
1394        case 'I':
1395            str = ip_ntoa(va_arg(args, u_int32_t));
1396            break;
1397        case 'r':
1398            f = va_arg(args, char *);
1399            a = va_arg(args, va_list);
1400            n = vfmtmsg(buf, buflen + 1, f, a);
1401            buf += n;
1402            buflen -= n;
1403            continue;
1404        case 't':
1405            time(&t);
1406            str = ctime(&t);
1407            str += 4;           /* chop off the day name */
1408            str[15] = 0;        /* chop off year and newline */
1409            break;
1410        case 'v':               /* "visible" string */
1411        case 'q':               /* quoted string */
1412            quoted = c == 'q';
1413            p = va_arg(args, unsigned char *);
1414            if (fillch == '0' && prec > 0) {
1415                n = prec;
1416            } else {
1417                n = strlen((char *)p);
1418                if (prec > 0 && prec < n)
1419                    n = prec;
1420            }
1421            while (n > 0 && buflen > 0) {
1422                c = *p++;
1423                --n;
1424                if (!quoted && c >= 0x80) {
1425                    OUTCHAR('M');
1426                    OUTCHAR('-');
1427                    c -= 0x80;
1428                }
1429                if (quoted && (c == '"' || c == '\\'))
1430                    OUTCHAR('\\');
1431                if (c < 0x20 || 0x7f <= c && c < 0xa0) {
1432                    if (quoted) {
1433                        OUTCHAR('\\');
1434                        switch (c) {
1435                        case '\t':      OUTCHAR('t');   break;
1436                        case '\n':      OUTCHAR('n');   break;
1437                        case '\b':      OUTCHAR('b');   break;
1438                        case '\f':      OUTCHAR('f');   break;
1439                        default:
1440                            OUTCHAR('x');
1441                            OUTCHAR(hexchars[c >> 4]);
1442                            OUTCHAR(hexchars[c & 0xf]);
1443                        }
1444                    } else {
1445                        if (c == '\t')
1446                            OUTCHAR(c);
1447                        else {
1448                            OUTCHAR('^');
1449                            OUTCHAR(c ^ 0x40);
1450                        }
1451                    }
1452                } else
1453                    OUTCHAR(c);
1454            }
1455            continue;
1456        default:
1457            *buf++ = '%';
1458            if (c != '%')
1459                --fmt;          /* so %z outputs %z etc. */
1460            --buflen;
1461            continue;
1462        }
1463        if (base != 0) {
1464            str = num + sizeof(num);
1465            *--str = 0;
1466            while (str > num + neg) {
1467                *--str = hexchars[val % base];
1468                val = val / base;
1469                if (--prec <= 0 && val == 0)
1470                    break;
1471            }
1472            switch (neg) {
1473            case 1:
1474                *--str = '-';
1475                break;
1476            case 2:
1477                *--str = 'x';
1478                *--str = '0';
1479                break;
1480            }
1481            len = num + sizeof(num) - 1 - str;
1482        } else {
1483            len = strlen(str);
1484            if (prec > 0 && len > prec)
1485                len = prec;
1486        }
1487        if (width > 0) {
1488            if (width > buflen)
1489                width = buflen;
1490            if ((n = width - len) > 0) {
1491                buflen -= n;
1492                for (; n > 0; --n)
1493                    *buf++ = fillch;
1494            }
1495        }
1496        if (len > buflen)
1497            len = buflen;
1498        memcpy(buf, str, len);
1499        buf += len;
1500        buflen -= len;
1501    }
1502    *buf = 0;
1503    return buf - buf0;
1504}
1505
1506