]> git.ozlabs.org Git - ppp.git/blob - pppd/main.c
gone to modules
[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.35 1996/08/28 06:41:16 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 PRIMITIVE_SYSLOG
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 PRIMITIVE_SYSLOG
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 #ifdef _linux_
519         disestablish_ppp(ttyfd);
520 #endif
521         if (demand)
522             restore_loop();
523 #ifndef _linux_
524         disestablish_ppp(ttyfd);
525 #endif
526
527         /*
528          * Run disconnector script, if requested.
529          * XXX we may not be able to do this if the line has hung up!
530          */
531         if (disconnector && !hungup) {
532             set_up_tty(ttyfd, 1);
533             if (device_script(disconnector, ttyfd, ttyfd) < 0) {
534                 syslog(LOG_WARNING, "disconnect script failed");
535             } else {
536                 syslog(LOG_INFO, "Serial link disconnected.");
537             }
538         }
539
540     fail:
541         close_tty();
542         if (locked) {
543             unlock();
544             locked = 0;
545         }
546
547         if (!demand) {
548             if (pidfilename[0] != 0
549                 && unlink(pidfilename) < 0 && errno != ENOENT) 
550                 syslog(LOG_WARNING, "unable to delete pid file: %m");
551             pidfilename[0] = 0;
552         }
553
554         if (!persist)
555             break;
556
557         if (demand)
558             demand_discard();
559         if (holdoff > 0 && need_holdoff) {
560             phase = PHASE_HOLDOFF;
561             TIMEOUT(holdoff_end, NULL, holdoff);
562             do {
563                 wait_time(timeleft(&timo));
564                 calltimeout();
565                 if (kill_link) {
566                     if (!persist)
567                         die(0);
568                     kill_link = 0;
569                     phase = PHASE_DORMANT; /* allow signal to end holdoff */
570                 }
571                 reap_kids();
572             } while (phase == PHASE_HOLDOFF);
573         }
574     }
575
576     die(0);
577 }
578
579 /*
580  * holdoff_end - called via a timeout when the holdoff period ends.
581  */
582 static void
583 holdoff_end(arg)
584     void *arg;
585 {
586     phase = PHASE_DORMANT;
587 }
588
589 /*
590  * get_input - called when incoming data is available.
591  */
592 static void
593 get_input()
594 {
595     int len, i;
596     u_char *p;
597     u_short protocol;
598     struct protent *protp;
599
600     p = inpacket_buf;   /* point to beginning of packet buffer */
601
602     len = read_packet(inpacket_buf);
603     if (len < 0)
604         return;
605
606     if (len == 0) {
607         syslog(LOG_NOTICE, "Modem hangup");
608         hungup = 1;
609         lcp_lowerdown(0);       /* serial link is no longer available */
610         link_terminated(0);
611         return;
612     }
613
614     if (debug /*&& (debugflags & DBG_INPACKET)*/)
615         log_packet(p, len, "rcvd ");
616
617     if (len < PPP_HDRLEN) {
618         MAINDEBUG((LOG_INFO, "io(): Received short packet."));
619         return;
620     }
621
622     p += 2;                             /* Skip address and control */
623     GETSHORT(protocol, p);
624     len -= PPP_HDRLEN;
625
626     /*
627      * Toss all non-LCP packets unless LCP is OPEN.
628      */
629     if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
630         MAINDEBUG((LOG_INFO,
631                    "io(): Received non-LCP packet when LCP not open."));
632         return;
633     }
634
635     /*
636      * Upcall the proper protocol input routine.
637      */
638     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
639         if (protp->protocol == protocol && protp->enabled_flag) {
640             (*protp->input)(0, p, len);
641             return;
642         }
643         if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
644             && protp->datainput != NULL) {
645             (*protp->datainput)(0, p, len);
646             return;
647         }
648     }
649
650     if (debug)
651         syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
652     lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
653 }
654
655
656 /*
657  * quit - Clean up state and exit (with an error indication).
658  */
659 void 
660 quit()
661 {
662     die(1);
663 }
664
665 /*
666  * die - like quit, except we can specify an exit status.
667  */
668 void
669 die(status)
670     int status;
671 {
672     cleanup();
673     syslog(LOG_INFO, "Exit.");
674     exit(status);
675 }
676
677 /*
678  * connect_time_expired - log a message and close the connection.
679  */
680 static void
681 connect_time_expired(arg)
682     caddr_t arg;
683 {
684     syslog(LOG_INFO, "Connect time expired");
685     lcp_close(0, "Connect time expired");       /* Close connection */
686 }
687
688 /*
689  * cleanup - restore anything which needs to be restored before we exit
690  */
691 /* ARGSUSED */
692 static void
693 cleanup()
694 {
695     sys_cleanup();
696
697     if (ttyfd >= 0)
698         close_tty();
699
700     if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) 
701         syslog(LOG_WARNING, "unable to delete pid file: %m");
702     pidfilename[0] = 0;
703
704     if (locked)
705         unlock();
706 }
707
708 /*
709  * close_tty - restore the terminal device and close it.
710  */
711 static void
712 close_tty()
713 {
714     disestablish_ppp(ttyfd);
715
716     /* drop dtr to hang up */
717     if (modem) {
718         setdtr(ttyfd, FALSE);
719         /*
720          * This sleep is in case the serial port has CLOCAL set by default,
721          * and consequently will reassert DTR when we close the device.
722          */
723         sleep(1);
724     }
725
726     restore_tty(ttyfd);
727
728     if (tty_mode != (mode_t) -1)
729         chmod(devnam, tty_mode);
730
731     close(ttyfd);
732     ttyfd = -1;
733 }
734
735
736 struct  callout {
737     struct timeval      c_time;         /* time at which to call routine */
738     caddr_t             c_arg;          /* argument to routine */
739     void                (*c_func)();    /* routine */
740     struct              callout *c_next;
741 };
742
743 static struct callout *callout = NULL;  /* Callout list */
744 static struct timeval timenow;          /* Current time */
745
746 /*
747  * timeout - Schedule a timeout.
748  *
749  * Note that this timeout takes the number of seconds, NOT hz (as in
750  * the kernel).
751  */
752 void
753 timeout(func, arg, time)
754     void (*func)();
755     caddr_t arg;
756     int time;
757 {
758     struct callout *newp, *p, **pp;
759   
760     MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
761                (long) func, (long) arg, time));
762   
763     /*
764      * Allocate timeout.
765      */
766     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
767         syslog(LOG_ERR, "Out of memory in timeout()!");
768         die(1);
769     }
770     newp->c_arg = arg;
771     newp->c_func = func;
772     gettimeofday(&timenow, NULL);
773     newp->c_time.tv_sec = timenow.tv_sec + time;
774     newp->c_time.tv_usec = timenow.tv_usec;
775   
776     /*
777      * Find correct place and link it in.
778      */
779     for (pp = &callout; (p = *pp); pp = &p->c_next)
780         if (newp->c_time.tv_sec < p->c_time.tv_sec
781             || (newp->c_time.tv_sec == p->c_time.tv_sec
782                 && newp->c_time.tv_usec < p->c_time.tv_sec))
783             break;
784     newp->c_next = p;
785     *pp = newp;
786 }
787
788
789 /*
790  * untimeout - Unschedule a timeout.
791  */
792 void
793 untimeout(func, arg)
794     void (*func)();
795     caddr_t arg;
796 {
797     struct callout **copp, *freep;
798   
799     MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));
800   
801     /*
802      * Find first matching timeout and remove it from the list.
803      */
804     for (copp = &callout; (freep = *copp); copp = &freep->c_next)
805         if (freep->c_func == func && freep->c_arg == arg) {
806             *copp = freep->c_next;
807             (void) free((char *) freep);
808             break;
809         }
810 }
811
812
813 /*
814  * calltimeout - Call any timeout routines which are now due.
815  */
816 static void
817 calltimeout()
818 {
819     struct callout *p;
820
821     while (callout != NULL) {
822         p = callout;
823
824         if (gettimeofday(&timenow, NULL) < 0) {
825             syslog(LOG_ERR, "Failed to get time of day: %m");
826             die(1);
827         }
828         if (!(p->c_time.tv_sec < timenow.tv_sec
829               || (p->c_time.tv_sec == timenow.tv_sec
830                   && p->c_time.tv_usec <= timenow.tv_usec)))
831             break;              /* no, it's not time yet */
832
833         callout = p->c_next;
834         (*p->c_func)(p->c_arg);
835
836         free((char *) p);
837     }
838 }
839
840
841 /*
842  * timeleft - return the length of time until the next timeout is due.
843  */
844 static struct timeval *
845 timeleft(tvp)
846     struct timeval *tvp;
847 {
848     if (callout == NULL)
849         return NULL;
850
851     gettimeofday(&timenow, NULL);
852     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
853     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
854     if (tvp->tv_usec < 0) {
855         tvp->tv_usec += 1000000;
856         tvp->tv_sec -= 1;
857     }
858     if (tvp->tv_sec < 0)
859         tvp->tv_sec = tvp->tv_usec = 0;
860
861     return tvp;
862 }
863
864
865 /*
866  * kill_my_pg - send a signal to our process group, and ignore it ourselves.
867  */
868 static void
869 kill_my_pg(sig)
870     int sig;
871 {
872     struct sigaction act, oldact;
873
874     act.sa_handler = SIG_IGN;
875     act.sa_flags = 0;
876     sigaction(sig, &act, &oldact);
877     kill(-getpgrp(), sig);
878     sigaction(sig, &oldact, NULL);
879 }
880
881
882 /*
883  * hup - Catch SIGHUP signal.
884  *
885  * Indicates that the physical layer has been disconnected.
886  * We don't rely on this indication; if the user has sent this
887  * signal, we just take the link down.
888  */
889 static void
890 hup(sig)
891     int sig;
892 {
893     syslog(LOG_INFO, "Hangup (SIGHUP)");
894     kill_link = 1;
895     if (conn_running)
896         /* Send the signal to the [dis]connector process(es) also */
897         kill_my_pg(sig);
898 }
899
900
901 /*
902  * term - Catch SIGTERM signal and SIGINT signal (^C/del).
903  *
904  * Indicates that we should initiate a graceful disconnect and exit.
905  */
906 /*ARGSUSED*/
907 static void
908 term(sig)
909     int sig;
910 {
911     syslog(LOG_INFO, "Terminating on signal %d.", sig);
912     persist = 0;                /* don't try to restart */
913     kill_link = 1;
914     if (conn_running)
915         /* Send the signal to the [dis]connector process(es) also */
916         kill_my_pg(sig);
917 }
918
919
920 /*
921  * chld - Catch SIGCHLD signal.
922  * Calls reap_kids to get status for any dead kids.
923  */
924 static void
925 chld(sig)
926     int sig;
927 {
928     reap_kids();
929 }
930
931
932 /*
933  * toggle_debug - Catch SIGUSR1 signal.
934  *
935  * Toggle debug flag.
936  */
937 /*ARGSUSED*/
938 static void
939 toggle_debug(sig)
940     int sig;
941 {
942     debug = !debug;
943     if (debug) {
944         setlogmask(LOG_UPTO(LOG_DEBUG));
945     } else {
946         setlogmask(LOG_UPTO(LOG_WARNING));
947     }
948 }
949
950
951 /*
952  * open_ccp - Catch SIGUSR2 signal.
953  *
954  * Try to (re)negotiate compression.
955  */
956 /*ARGSUSED*/
957 static void
958 open_ccp(sig)
959     int sig;
960 {
961     open_ccp_flag = 1;
962 }
963
964
965 /*
966  * bad_signal - We've caught a fatal signal.  Clean up state and exit.
967  */
968 static void
969 bad_signal(sig)
970     int sig;
971 {
972     syslog(LOG_ERR, "Fatal signal %d", sig);
973     if (conn_running)
974         kill_my_pg(SIGTERM);
975     die(1);
976 }
977
978
979 /*
980  * device_script - run a program to connect or disconnect the
981  * serial device.
982  */
983 static int
984 device_script(program, in, out)
985     char *program;
986     int in, out;
987 {
988     int pid;
989     int status;
990     int errfd;
991
992     conn_running = 1;
993     pid = fork();
994
995     if (pid < 0) {
996         conn_running = 0;
997         syslog(LOG_ERR, "Failed to create child process: %m");
998         die(1);
999     }
1000
1001     if (pid == 0) {
1002         sys_close();
1003         closelog();
1004         if (in == out) {
1005             if (in != 0) {
1006                 dup2(in, 0);
1007                 close(in);
1008             }
1009             dup2(0, 1);
1010         } else {
1011             if (out == 0)
1012                 out = dup(out);
1013             if (in != 0) {
1014                 dup2(in, 0);
1015                 close(in);
1016             }
1017             if (out != 1) {
1018                 dup2(out, 1);
1019                 close(out);
1020             }
1021         }
1022         if (redirect_stderr) {
1023             close(2);
1024             errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644);
1025             if (errfd >= 0 && errfd != 2) {
1026                 dup2(errfd, 2);
1027                 close(errfd);
1028             }
1029         }
1030         setuid(getuid());
1031         setgid(getgid());
1032         execl("/bin/sh", "sh", "-c", program, (char *)0);
1033         syslog(LOG_ERR, "could not exec /bin/sh: %m");
1034         _exit(99);
1035         /* NOTREACHED */
1036     }
1037
1038     while (waitpid(pid, &status, 0) < 0) {
1039         if (errno == EINTR)
1040             continue;
1041         syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
1042         die(1);
1043     }
1044     conn_running = 0;
1045
1046     return (status == 0 ? 0 : -1);
1047 }
1048
1049
1050 /*
1051  * run-program - execute a program with given arguments,
1052  * but don't wait for it.
1053  * If the program can't be executed, logs an error unless
1054  * must_exist is 0 and the program file doesn't exist.
1055  */
1056 int
1057 run_program(prog, args, must_exist)
1058     char *prog;
1059     char **args;
1060     int must_exist;
1061 {
1062     int pid;
1063     char *nullenv[1];
1064
1065     pid = fork();
1066     if (pid == -1) {
1067         syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
1068         return -1;
1069     }
1070     if (pid == 0) {
1071         int new_fd;
1072
1073         /* Leave the current location */
1074         (void) setsid();    /* No controlling tty. */
1075         (void) umask (S_IRWXG|S_IRWXO);
1076         (void) chdir ("/"); /* no current directory. */
1077         setuid(geteuid());
1078         setgid(getegid());
1079
1080         /* Ensure that nothing of our device environment is inherited. */
1081         sys_close();
1082         closelog();
1083         close (0);
1084         close (1);
1085         close (2);
1086         close (ttyfd);  /* tty interface to the ppp device */
1087
1088         /* Don't pass handles to the PPP device, even by accident. */
1089         new_fd = open (_PATH_DEVNULL, O_RDWR);
1090         if (new_fd >= 0) {
1091             if (new_fd != 0) {
1092                 dup2  (new_fd, 0); /* stdin <- /dev/null */
1093                 close (new_fd);
1094             }
1095             dup2 (0, 1); /* stdout -> /dev/null */
1096             dup2 (0, 2); /* stderr -> /dev/null */
1097         }
1098
1099 #ifdef BSD
1100         /* Force the priority back to zero if pppd is running higher. */
1101         if (setpriority (PRIO_PROCESS, 0, 0) < 0)
1102             syslog (LOG_WARNING, "can't reset priority to 0: %m"); 
1103 #endif
1104
1105         /* SysV recommends a second fork at this point. */
1106
1107         /* run the program; give it a null environment */
1108         nullenv[0] = NULL;
1109         execve(prog, args, nullenv);
1110         if (must_exist || errno != ENOENT)
1111             syslog(LOG_WARNING, "Can't execute %s: %m", prog);
1112         _exit(-1);
1113     }
1114     MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
1115     ++n_children;
1116     return 0;
1117 }
1118
1119
1120 /*
1121  * reap_kids - get status from any dead child processes,
1122  * and log a message for abnormal terminations.
1123  */
1124 static void
1125 reap_kids()
1126 {
1127     int pid, status;
1128
1129     if (n_children == 0)
1130         return;
1131     if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
1132         if (errno != ECHILD)
1133             syslog(LOG_ERR, "Error waiting for child process: %m");
1134         return;
1135     }
1136     if (pid > 0) {
1137         --n_children;
1138         if (WIFSIGNALED(status)) {
1139             syslog(LOG_WARNING, "Child process %d terminated with signal %d",
1140                    pid, WTERMSIG(status));
1141         }
1142     }
1143 }
1144
1145
1146 /*
1147  * log_packet - format a packet and log it.
1148  */
1149
1150 char line[256];                 /* line to be logged accumulated here */
1151 char *linep;
1152
1153 void
1154 log_packet(p, len, prefix)
1155     u_char *p;
1156     int len;
1157     char *prefix;
1158 {
1159     strcpy(line, prefix);
1160     linep = line + strlen(line);
1161     format_packet(p, len, pr_log, NULL);
1162     if (linep != line)
1163         syslog(LOG_DEBUG, "%s", line);
1164 }
1165
1166 /*
1167  * format_packet - make a readable representation of a packet,
1168  * calling `printer(arg, format, ...)' to output it.
1169  */
1170 void
1171 format_packet(p, len, printer, arg)
1172     u_char *p;
1173     int len;
1174     void (*printer) __P((void *, char *, ...));
1175     void *arg;
1176 {
1177     int i, n;
1178     u_short proto;
1179     u_char x;
1180     struct protent *protp;
1181
1182     if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
1183         p += 2;
1184         GETSHORT(proto, p);
1185         len -= PPP_HDRLEN;
1186         for (i = 0; (protp = protocols[i]) != NULL; ++i)
1187             if (proto == protp->protocol)
1188                 break;
1189         if (protp != NULL) {
1190             printer(arg, "[%s", protp->name);
1191             n = (*protp->printpkt)(p, len, printer, arg);
1192             printer(arg, "]");
1193             p += n;
1194             len -= n;
1195         } else {
1196             printer(arg, "[proto=0x%x]", proto);
1197         }
1198     }
1199
1200     for (; len > 0; --len) {
1201         GETCHAR(x, p);
1202         printer(arg, " %.2x", x);
1203     }
1204 }
1205
1206 static void
1207 pr_log __V((void *arg, char *fmt, ...))
1208 {
1209     int n;
1210     va_list pvar;
1211     char buf[256];
1212
1213 #if __STDC__
1214     va_start(pvar, fmt);
1215 #else
1216     void *arg;
1217     char *fmt;
1218     va_start(pvar);
1219     arg = va_arg(pvar, void *);
1220     fmt = va_arg(pvar, char *);
1221 #endif
1222
1223     vsprintf(buf, fmt, pvar);
1224     va_end(pvar);
1225
1226     n = strlen(buf);
1227     if (linep + n + 1 > line + sizeof(line)) {
1228         syslog(LOG_DEBUG, "%s", line);
1229         linep = line;
1230     }
1231     strcpy(linep, buf);
1232     linep += n;
1233 }
1234
1235 /*
1236  * print_string - print a readable representation of a string using
1237  * printer.
1238  */
1239 void
1240 print_string(p, len, printer, arg)
1241     char *p;
1242     int len;
1243     void (*printer) __P((void *, char *, ...));
1244     void *arg;
1245 {
1246     int c;
1247
1248     printer(arg, "\"");
1249     for (; len > 0; --len) {
1250         c = *p++;
1251         if (' ' <= c && c <= '~') {
1252             if (c == '\\' || c == '"')
1253                 printer(arg, "\\");
1254             printer(arg, "%c", c);
1255         } else {
1256             switch (c) {
1257             case '\n':
1258                 printer(arg, "\\n");
1259                 break;
1260             case '\r':
1261                 printer(arg, "\\r");
1262                 break;
1263             case '\t':
1264                 printer(arg, "\\t");
1265                 break;
1266             default:
1267                 printer(arg, "\\%.3o", c);
1268             }
1269         }
1270     }
1271     printer(arg, "\"");
1272 }
1273
1274 /*
1275  * novm - log an error message saying we ran out of memory, and die.
1276  */
1277 void
1278 novm(msg)
1279     char *msg;
1280 {
1281     syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
1282     die(1);
1283 }
1284
1285 /*
1286  * fmtmsg - format a message into a buffer.  Like sprintf except we
1287  * also specify the length of the output buffer, and we handle
1288  * %r (recursive format), %m (error message) and %I (IP address) formats.
1289  * Doesn't do floating-point formats.
1290  * Returns the number of chars put into buf.
1291  */
1292 int
1293 fmtmsg __V((char *buf, int buflen, char *fmt, ...))
1294 {
1295     va_list args;
1296     int n;
1297
1298 #if __STDC__
1299     va_start(args, fmt);
1300 #else
1301     char *buf;
1302     int buflen;
1303     char *fmt;
1304     va_start(args);
1305     buf = va_arg(args, char *);
1306     buflen = va_arg(args, int);
1307     fmt = va_arg(args, char *);
1308 #endif
1309     n = vfmtmsg(buf, buflen, fmt, args);
1310     va_end(args);
1311     return n;
1312 }
1313
1314 /*
1315  * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
1316  */
1317 #define OUTCHAR(c)      (buflen > 0? (--buflen, *buf++ = (c)): 0)
1318
1319 int
1320 vfmtmsg(char *buf, int buflen, char *fmt, va_list args)
1321 {
1322     int c, i, n;
1323     int width, prec, fillch;
1324     int base, len, neg, quoted;
1325     unsigned long val;
1326     char *str, *f, *buf0;
1327     unsigned char *p;
1328     va_list a;
1329     char num[32];
1330     time_t t;
1331     static char hexchars[16] = "0123456789abcdef";
1332
1333     buf0 = buf;
1334     --buflen;
1335     while (buflen > 0) {
1336         for (f = fmt; *f != '%' && *f != 0; ++f)
1337             ;
1338         if (f > fmt) {
1339             len = f - fmt;
1340             if (len > buflen)
1341                 len = buflen;
1342             memcpy(buf, fmt, len);
1343             buf += len;
1344             buflen -= len;
1345             fmt = f;
1346         }
1347         if (*fmt == 0)
1348             break;
1349         c = *++fmt;
1350         width = prec = 0;
1351         fillch = ' ';
1352         if (c == '0') {
1353             fillch = '0';
1354             c = *++fmt;
1355         }
1356         if (c == '*') {
1357             width = va_arg(args, int);
1358             c = *++fmt;
1359         } else {
1360             while (isdigit(c)) {
1361                 width = width * 10 + c - '0';
1362                 c = *++fmt;
1363             }
1364         }
1365         if (c == '.') {
1366             c = *++fmt;
1367             if (c == '*') {
1368                 prec = va_arg(args, int);
1369                 c = *++fmt;
1370             } else {
1371                 while (isdigit(c)) {
1372                     prec = prec * 10 + c - '0';
1373                     c = *++fmt;
1374                 }
1375             }
1376         }
1377         str = 0;
1378         base = 0;
1379         neg = 0;
1380         ++fmt;
1381         switch (c) {
1382         case 'd':
1383             i = va_arg(args, int);
1384             if (i < 0) {
1385                 neg = 1;
1386                 val = -i;
1387             } else
1388                 val = i;
1389             base = 10;
1390             break;
1391         case 'o':
1392             val = va_arg(args, unsigned int);
1393             base = 8;
1394             break;
1395         case 'x':
1396             val = va_arg(args, unsigned int);
1397             base = 16;
1398             break;
1399         case 'p':
1400             val = (unsigned long) va_arg(args, void *);
1401             base = 16;
1402             neg = 2;
1403             break;
1404         case 's':
1405             str = va_arg(args, char *);
1406             break;
1407         case 'c':
1408             num[0] = va_arg(args, int);
1409             num[1] = 0;
1410             str = num;
1411             break;
1412         case 'm':
1413             str = strerror(errno);
1414             break;
1415         case 'I':
1416             str = ip_ntoa(va_arg(args, u_int32_t));
1417             break;
1418         case 'r':
1419             f = va_arg(args, char *);
1420             a = va_arg(args, va_list);
1421             n = vfmtmsg(buf, buflen + 1, f, a);
1422             buf += n;
1423             buflen -= n;
1424             continue;
1425         case 't':
1426             time(&t);
1427             str = ctime(&t);
1428             str += 4;           /* chop off the day name */
1429             str[15] = 0;        /* chop off year and newline */
1430             break;
1431         case 'v':               /* "visible" string */
1432         case 'q':               /* quoted string */
1433             quoted = c == 'q';
1434             p = va_arg(args, unsigned char *);
1435             if (fillch == '0' && prec > 0) {
1436                 n = prec;
1437             } else {
1438                 n = strlen((char *)p);
1439                 if (prec > 0 && prec < n)
1440                     n = prec;
1441             }
1442             while (n > 0 && buflen > 0) {
1443                 c = *p++;
1444                 --n;
1445                 if (!quoted && c >= 0x80) {
1446                     OUTCHAR('M');
1447                     OUTCHAR('-');
1448                     c -= 0x80;
1449                 }
1450                 if (quoted && (c == '"' || c == '\\'))
1451                     OUTCHAR('\\');
1452                 if (c < 0x20 || 0x7f <= c && c < 0xa0) {
1453                     if (quoted) {
1454                         OUTCHAR('\\');
1455                         switch (c) {
1456                         case '\t':      OUTCHAR('t');   break;
1457                         case '\n':      OUTCHAR('n');   break;
1458                         case '\b':      OUTCHAR('b');   break;
1459                         case '\f':      OUTCHAR('f');   break;
1460                         default:
1461                             OUTCHAR('x');
1462                             OUTCHAR(hexchars[c >> 4]);
1463                             OUTCHAR(hexchars[c & 0xf]);
1464                         }
1465                     } else {
1466                         if (c == '\t')
1467                             OUTCHAR(c);
1468                         else {
1469                             OUTCHAR('^');
1470                             OUTCHAR(c ^ 0x40);
1471                         }
1472                     }
1473                 } else
1474                     OUTCHAR(c);
1475             }
1476             continue;
1477         default:
1478             *buf++ = '%';
1479             if (c != '%')
1480                 --fmt;          /* so %z outputs %z etc. */
1481             --buflen;
1482             continue;
1483         }
1484         if (base != 0) {
1485             str = num + sizeof(num);
1486             *--str = 0;
1487             while (str > num + neg) {
1488                 *--str = hexchars[val % base];
1489                 val = val / base;
1490                 if (--prec <= 0 && val == 0)
1491                     break;
1492             }
1493             switch (neg) {
1494             case 1:
1495                 *--str = '-';
1496                 break;
1497             case 2:
1498                 *--str = 'x';
1499                 *--str = '0';
1500                 break;
1501             }
1502             len = num + sizeof(num) - 1 - str;
1503         } else {
1504             len = strlen(str);
1505             if (prec > 0 && len > prec)
1506                 len = prec;
1507         }
1508         if (width > 0) {
1509             if (width > buflen)
1510                 width = buflen;
1511             if ((n = width - len) > 0) {
1512                 buflen -= n;
1513                 for (; n > 0; --n)
1514                     *buf++ = fillch;
1515             }
1516         }
1517         if (len > buflen)
1518             len = buflen;
1519         memcpy(buf, str, len);
1520         buf += len;
1521         buflen -= len;
1522     }
1523     *buf = 0;
1524     return buf - buf0;
1525 }