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