]> git.ozlabs.org Git - ppp.git/blob - pppd/main.c
4d165732096eb647ca707c091c630c1576cac4af
[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.18 1994/09/01 00:32:24 paulus Exp $";
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <signal.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <syslog.h>
30 #include <netdb.h>
31 #include <utmp.h>
32 #include <pwd.h>
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <sys/time.h>
37 #include <sys/resource.h>
38 #include <sys/stat.h>
39 #include <sys/socket.h>
40 #include <net/if.h>
41
42 #include "ppp.h"
43 #include "pppd.h"
44 #include "magic.h"
45 #include "fsm.h"
46 #include "lcp.h"
47 #include "ipcp.h"
48 #include "upap.h"
49 #include "chap.h"
50 #include "ccp.h"
51 #include "pathnames.h"
52 #include "patchlevel.h"
53
54 /*
55  * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless
56  * /etc/ppp/options exists.
57  */
58 #ifndef REQ_SYSOPTIONS
59 #define REQ_SYSOPTIONS  1
60 #endif
61
62 /* interface vars */
63 char ifname[IFNAMSIZ];          /* Interface name */
64 int ifunit;                     /* Interface unit number */
65
66 char *progname;                 /* Name of this program */
67 char hostname[MAXNAMELEN];      /* Our hostname */
68 static char pidfilename[MAXPATHLEN];
69
70 static pid_t    pid;            /* Our pid */
71 static pid_t    pgrpid;         /* Process Group ID */
72 static uid_t uid;               /* Our real user-id */
73
74 int fd = -1;                    /* Device file descriptor */
75 int s;                          /* Socket file descriptor */
76
77 int phase;                      /* where the link is at */
78 int kill_link;
79 int open_ccp_flag;
80
81 static int initfdflags = -1;    /* Initial file descriptor flags */
82
83 u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */
84 static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* buffer for incoming packet */
85
86 int hungup;                     /* terminal has been hung up */
87 static int n_children;          /* # child processes still running */
88
89 int baud_rate;
90
91 /* prototypes */
92 static void hup __ARGS((int));
93 static void term __ARGS((int));
94 static void chld __ARGS((int));
95 static void toggle_debug __ARGS((int));
96 static void open_ccp __ARGS((int));
97
98 static void get_input __ARGS((void));
99 void establish_ppp __ARGS((void));
100 void calltimeout __ARGS((void));
101 struct timeval *timeleft __ARGS((struct timeval *));
102 void reap_kids __ARGS((void));
103 void cleanup __ARGS((int, caddr_t));
104 void close_fd __ARGS((void));
105 void die __ARGS((int));
106 void novm __ARGS((char *));
107
108 void log_packet __ARGS((u_char *, int, char *));
109 void format_packet __ARGS((u_char *, int,
110                            void (*) (void *, char *, ...), void *));
111 void pr_log __ARGS((void *, char *, ...));
112
113 extern  char    *ttyname __ARGS((int));
114 extern  char    *getlogin __ARGS((void));
115
116 /*
117  * PPP Data Link Layer "protocol" table.
118  * One entry per supported protocol.
119  */
120 static struct protent {
121     u_short protocol;
122     void (*init)();
123     void (*input)();
124     void (*protrej)();
125     int  (*printpkt)();
126     void (*datainput)();
127     char *name;
128 } prottbl[] = {
129     { LCP, lcp_init, lcp_input, lcp_protrej, lcp_printpkt, NULL, "LCP" },
130     { IPCP, ipcp_init, ipcp_input, ipcp_protrej, ipcp_printpkt, NULL, "IPCP" },
131     { UPAP, upap_init, upap_input, upap_protrej, upap_printpkt, NULL, "PAP" },
132     { CHAP, ChapInit, ChapInput, ChapProtocolReject, ChapPrintPkt, NULL, "CHAP" },
133     { CCP, ccp_init, ccp_input, ccp_protrej, ccp_printpkt, ccp_datainput, "CCP" },
134 };
135
136 #define N_PROTO         (sizeof(prottbl) / sizeof(prottbl[0]))
137
138 main(argc, argv)
139     int argc;
140     char *argv[];
141 {
142     int i, nonblock;
143     struct sigaction sa;
144     struct cmd *cmdp;
145     FILE *pidfile;
146     char *p;
147     struct passwd *pw;
148     struct timeval timo;
149     sigset_t mask;
150
151     p = ttyname(0);
152     if (p)
153         strcpy(devnam, p);
154
155     if (gethostname(hostname, MAXNAMELEN) < 0 ) {
156         perror("couldn't get hostname");
157         die(1);
158     }
159     hostname[MAXNAMELEN-1] = 0;
160
161     uid = getuid();
162
163     if (!ppp_available()) {
164         fprintf(stderr, "Sorry - PPP is not available on this system\n");
165         exit(1);
166     }
167
168     /*
169      * Initialize to the standard option set, then parse, in order,
170      * the system options file, the user's options file, and the command
171      * line arguments.
172      */
173     for (i = 0; i < N_PROTO; i++)
174         (*prottbl[i].init)(0);
175   
176     progname = *argv;
177
178     if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) ||
179         !options_from_user() ||
180         !parse_args(argc-1, argv+1) ||
181         !options_for_tty())
182         die(1);
183     check_auth_options();
184     setipdefault();
185
186     /*
187      * Initialize system-dependent stuff and magic number package.
188      */
189     sys_init();
190     magic_init();
191
192     /*
193      * Detach ourselves from the terminal, if required,
194      * and identify who is running us.
195      */
196     if (!default_device && !nodetach && daemon(0, 0) < 0) {
197         perror("Couldn't detach from controlling terminal");
198         exit(1);
199     }
200     pid = getpid();
201     p = getlogin();
202     if (p == NULL) {
203         pw = getpwuid(uid);
204         if (pw != NULL && pw->pw_name != NULL)
205             p = pw->pw_name;
206         else
207             p = "(unknown)";
208     }
209     syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d",
210            VERSION, PATCHLEVEL, p, uid);
211
212     /* Get an internet socket for doing socket ioctl's on. */
213     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
214         syslog(LOG_ERR, "Couldn't create IP socket: %m");
215         die(1);
216     }
217   
218     /*
219      * Compute mask of all interesting signals and install signal handlers
220      * for each.  Only one signal handler may be active at a time.  Therefore,
221      * all other signals should be masked when any handler is executing.
222      */
223     sigemptyset(&mask);
224     sigaddset(&mask, SIGHUP);
225     sigaddset(&mask, SIGINT);
226     sigaddset(&mask, SIGTERM);
227     sigaddset(&mask, SIGCHLD);
228
229 #define SIGNAL(s, handler)      { \
230         sa.sa_handler = handler; \
231         if (sigaction(s, &sa, NULL) < 0) { \
232             syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
233             die(1); \
234         } \
235     }
236
237     sa.sa_mask = mask;
238     sa.sa_flags = 0;
239     SIGNAL(SIGHUP, hup);                /* Hangup */
240     SIGNAL(SIGINT, term);               /* Interrupt */
241     SIGNAL(SIGTERM, term);              /* Terminate */
242     SIGNAL(SIGCHLD, chld);
243
244     signal(SIGUSR1, toggle_debug);      /* Toggle debug flag */
245     signal(SIGUSR2, open_ccp);          /* Reopen CCP */
246
247     /*
248      * Lock the device if we've been asked to.
249      */
250     if (lockflag && !default_device)
251         if (lock(devnam) < 0)
252             die(1);
253
254     do {
255
256         /*
257          * Open the serial device and set it up to be the ppp interface.
258          * If we're dialling out, or we don't want to use the modem lines,
259          * we open it in non-blocking mode, but then we need to clear
260          * the non-blocking I/O bit.
261          */
262         nonblock = (connector || !modem)? O_NONBLOCK: 0;
263         if ((fd = open(devnam, nonblock | O_RDWR, 0)) < 0) {
264             syslog(LOG_ERR, "Failed to open %s: %m", devnam);
265             die(1);
266         }
267         if ((initfdflags = fcntl(fd, F_GETFL)) == -1) {
268             syslog(LOG_ERR, "Couldn't get device fd flags: %m");
269             die(1);
270         }
271         if (nonblock) {
272             initfdflags &= ~O_NONBLOCK;
273             fcntl(fd, F_SETFL, initfdflags);
274         }
275         hungup = 0;
276         kill_link = 0;
277
278         /* run connection script */
279         if (connector && connector[0]) {
280             MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
281
282             /* set line speed, flow control, etc.; set CLOCAL for now */
283             set_up_tty(fd, 1);
284
285             /* drop dtr to hang up in case modem is off hook */
286             if (!default_device && modem) {
287                 setdtr(fd, FALSE);
288                 sleep(1);
289                 setdtr(fd, TRUE);
290             }
291
292             if (device_script(connector, fd, fd) < 0) {
293                 syslog(LOG_ERR, "Connect script failed");
294                 setdtr(fd, FALSE);
295                 die(1);
296             }
297
298             syslog(LOG_INFO, "Connected...");
299             sleep(1);           /* give it time to set up its terminal */
300         }
301   
302         /* set line speed, flow control, etc.; clear CLOCAL if modem option */
303         set_up_tty(fd, 0);
304
305         /* set up the serial device as a ppp interface */
306         establish_ppp();
307
308         syslog(LOG_INFO, "Using interface ppp%d", ifunit);
309         (void) sprintf(ifname, "ppp%d", ifunit);
310
311         /* write pid to file */
312         (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
313         if ((pidfile = fopen(pidfilename, "w")) != NULL) {
314             fprintf(pidfile, "%d\n", pid);
315             (void) fclose(pidfile);
316         } else {
317             syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename);
318             pidfilename[0] = 0;
319         }
320
321         /*
322          * Set device for non-blocking reads.
323          */
324         if (fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
325             syslog(LOG_ERR, "Couldn't set device to non-blocking mode: %m");
326             die(1);
327         }
328   
329         /*
330          * Block all signals, start opening the connection, and wait for
331          * incoming events (reply, timeout, etc.).
332          */
333         syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
334         lcp_lowerup(0);
335         lcp_open(0);            /* Start protocol */
336         for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
337             wait_input(timeleft(&timo));
338             calltimeout();
339             if (kill_link) {
340                 lcp_close(0);
341                 kill_link = 0;
342             }
343             if (open_ccp_flag) {
344                 if (phase == PHASE_NETWORK) {
345                     ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
346                     ccp_open(0);
347                 }
348                 open_ccp_flag = 0;
349             }
350             get_input();
351             reap_kids();        /* Don't leave dead kids lying around */
352         }
353
354         /*
355          * Run disconnector script, if requested
356          */
357         if (disconnector) {
358             if (device_script(disconnector, fd, fd) < 0) {
359                 syslog(LOG_WARNING, "disconnect script failed");
360                 die(1);
361             }
362
363             syslog(LOG_INFO, "Disconnected...");
364         }
365
366         close_fd();
367         if (unlink(pidfilename) < 0 && errno != ENOENT) 
368             syslog(LOG_WARNING, "unable to delete pid file: %m");
369         pidfilename[0] = 0;
370
371     } while (persist);
372
373     if (lockflag && !default_device)
374         unlock();
375
376     exit(0);
377 }
378
379
380 /*
381  * get_input - called when incoming data is available.
382  */
383 static void
384 get_input()
385 {
386     int len, i;
387     u_char *p;
388     u_short protocol;
389
390     for (;;) {                  /* Read all available packets */
391         p = inpacket_buf;       /* point to beginning of packet buffer */
392
393         len = read_packet(inpacket_buf);
394         if (len < 0)
395             return;
396
397         if (len == 0) {
398             MAINDEBUG((LOG_DEBUG, "End of file on fd!"));
399             hungup = 1;
400             lcp_lowerdown(0);   /* serial link is no longer available */
401             phase = PHASE_DEAD;
402             return;
403         }
404
405         if (debug /*&& (debugflags & DBG_INPACKET)*/)
406             log_packet(p, len, "rcvd ");
407
408         if (len < DLLHEADERLEN) {
409             MAINDEBUG((LOG_INFO, "io(): Received short packet."));
410             return;
411         }
412
413         p += 2;                         /* Skip address and control */
414         GETSHORT(protocol, p);
415         len -= DLLHEADERLEN;
416
417         /*
418          * Toss all non-LCP packets unless LCP is OPEN.
419          */
420         if (protocol != LCP && lcp_fsm[0].state != OPENED) {
421             MAINDEBUG((LOG_INFO,
422                        "io(): Received non-LCP packet when LCP not open."));
423             return;
424         }
425
426         /*
427          * Upcall the proper protocol input routine.
428          */
429         for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
430             if (prottbl[i].protocol == protocol) {
431                 (*prottbl[i].input)(0, p, len);
432                 break;
433             } else if (protocol == (prottbl[i].protocol & ~0x8000)
434                        && prottbl[i].datainput != NULL) {
435                 (*prottbl[i].datainput)(0, p, len);
436                 break;
437             }
438
439         if (i == sizeof (prottbl) / sizeof (struct protent)) {
440             if (debug)
441                 syslog(LOG_WARNING, "Unknown protocol (0x%x) received",
442                        protocol);
443             lcp_sprotrej(0, p - DLLHEADERLEN, len + DLLHEADERLEN);
444         }
445     }
446 }
447
448
449 /*
450  * demuxprotrej - Demultiplex a Protocol-Reject.
451  */
452 void
453 demuxprotrej(unit, protocol)
454     int unit;
455     u_short protocol;
456 {
457     int i;
458
459     /*
460      * Upcall the proper Protocol-Reject routine.
461      */
462     for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
463         if (prottbl[i].protocol == protocol) {
464             (*prottbl[i].protrej)(unit);
465             return;
466         }
467
468     syslog(LOG_WARNING,
469            "demuxprotrej: Unrecognized Protocol-Reject for protocol 0x%x",
470            protocol);
471 }
472
473
474 /*
475  * quit - Clean up state and exit.
476  */
477 void 
478 quit()
479 {
480     die(0);
481 }
482
483 /*
484  * die - like quit, except we can specify an exit status.
485  */
486 void
487 die(status)
488     int status;
489 {
490     cleanup(0, NULL);
491     syslog(LOG_INFO, "Exit.");
492     exit(status);
493 }
494
495 /*
496  * cleanup - restore anything which needs to be restored before we exit
497  */
498 /* ARGSUSED */
499 void
500 cleanup(status, arg)
501     int status;
502     caddr_t arg;
503 {
504     if (fd >= 0)
505         close_fd();
506
507     if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) 
508         syslog(LOG_WARNING, "unable to delete pid file: %m");
509     pidfilename[0] = 0;
510
511     if (lockflag && !default_device)
512         unlock();
513 }
514
515 /*
516  * close_fd - restore the terminal device and close it.
517  */
518 void
519 close_fd()
520 {
521     /* drop dtr to hang up */
522     if (modem)
523         setdtr(fd, FALSE);
524
525     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
526         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
527     initfdflags = -1;
528
529     disestablish_ppp();
530
531     restore_tty();
532
533     close(fd);
534     fd = -1;
535 }
536
537
538 struct  callout {
539     struct timeval      c_time;         /* time at which to call routine */
540     caddr_t             c_arg;          /* argument to routine */
541     void                (*c_func)();    /* routine */
542     struct              callout *c_next;
543 };
544
545 static struct callout *callout = NULL;  /* Callout list */
546 static struct timeval timenow;          /* Current time */
547
548 /*
549  * timeout - Schedule a timeout.
550  *
551  * Note that this timeout takes the number of seconds, NOT hz (as in
552  * the kernel).
553  */
554 void
555 timeout(func, arg, time)
556     void (*func)();
557     caddr_t arg;
558     int time;
559 {
560     struct callout *newp, *p, **pp;
561   
562     MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.",
563                (int) func, (int) arg, time));
564   
565     /*
566      * Allocate timeout.
567      */
568     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
569         syslog(LOG_ERR, "Out of memory in timeout()!");
570         die(1);
571     }
572     newp->c_arg = arg;
573     newp->c_func = func;
574     gettimeofday(&timenow, NULL);
575     newp->c_time.tv_sec = timenow.tv_sec + time;
576     newp->c_time.tv_usec = timenow.tv_usec;
577   
578     /*
579      * Find correct place and link it in.
580      */
581     for (pp = &callout; (p = *pp); pp = &p->c_next)
582         if (p->c_time.tv_sec < newp->c_time.tv_sec
583             || (p->c_time.tv_sec == newp->c_time.tv_sec
584                 && p->c_time.tv_usec <= newp->c_time.tv_sec))
585             break;
586     newp->c_next = p;
587     *pp = newp;
588 }
589
590
591 /*
592  * untimeout - Unschedule a timeout.
593  */
594 void
595 untimeout(func, arg)
596     void (*func)();
597     caddr_t arg;
598 {
599     struct itimerval itv;
600     struct callout **copp, *freep;
601     int reschedule = 0;
602   
603     MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg));
604   
605     /*
606      * Find first matching timeout and remove it from the list.
607      */
608     for (copp = &callout; (freep = *copp); copp = &freep->c_next)
609         if (freep->c_func == func && freep->c_arg == arg) {
610             *copp = freep->c_next;
611             (void) free((char *) freep);
612             break;
613         }
614 }
615
616
617 /*
618  * calltimeout - Call any timeout routines which are now due.
619  */
620 void
621 calltimeout()
622 {
623     struct callout *p;
624
625     while (callout != NULL) {
626         p = callout;
627
628         if (gettimeofday(&timenow, NULL) < 0) {
629             syslog(LOG_ERR, "Failed to get time of day: %m");
630             die(1);
631         }
632         if (!(p->c_time.tv_sec < timenow.tv_sec
633               || (p->c_time.tv_sec == timenow.tv_sec
634                   && p->c_time.tv_usec <= timenow.tv_usec)))
635             break;              /* no, it's not time yet */
636
637         callout = p->c_next;
638         (*p->c_func)(p->c_arg);
639
640         free((char *) p);
641     }
642 }
643
644
645 /*
646  * timeleft - return the length of time until the next timeout is due.
647  */
648 struct timeval *
649 timeleft(tvp)
650     struct timeval *tvp;
651 {
652     if (callout == NULL)
653         return NULL;
654
655     gettimeofday(&timenow, NULL);
656     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
657     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
658     if (tvp->tv_usec < 0) {
659         tvp->tv_usec += 1000000;
660         tvp->tv_sec -= 1;
661     }
662     if (tvp->tv_sec < 0)
663         tvp->tv_sec = tvp->tv_usec = 0;
664
665     return tvp;
666 }
667     
668
669 /*
670  * hup - Catch SIGHUP signal.
671  *
672  * Indicates that the physical layer has been disconnected.
673  * We don't rely on this indication; if the user has sent this
674  * signal, we just take the link down.
675  */
676 static void
677 hup(sig)
678     int sig;
679 {
680     syslog(LOG_INFO, "Hangup (SIGHUP)");
681     kill_link = 1;
682 }
683
684
685 /*
686  * term - Catch SIGTERM signal and SIGINT signal (^C/del).
687  *
688  * Indicates that we should initiate a graceful disconnect and exit.
689  */
690 /*ARGSUSED*/
691 static void
692 term(sig)
693     int sig;
694 {
695     syslog(LOG_INFO, "Terminating on signal %d.", sig);
696     persist = 0;                /* don't try to restart */
697     kill_link = 1;
698 }
699
700
701 /*
702  * chld - Catch SIGCHLD signal.
703  * Calls reap_kids to get status for any dead kids.
704  */
705 static void
706 chld(sig)
707     int sig;
708 {
709     reap_kids();
710 }
711
712
713 /*
714  * toggle_debug - Catch SIGUSR1 signal.
715  *
716  * Toggle debug flag.
717  */
718 /*ARGSUSED*/
719 static void
720 toggle_debug(sig)
721     int sig;
722 {
723     debug = !debug;
724     note_debug_level();
725 }
726
727
728 /*
729  * open_ccp - Catch SIGUSR2 signal.
730  *
731  * Try to (re)negotiate compression.
732  */
733 /*ARGSUSED*/
734 static void
735 open_ccp(sig)
736     int sig;
737 {
738     open_ccp_flag = 1;
739 }
740
741
742 /*
743  * device_script - run a program to connect or disconnect the
744  * serial device.
745  */
746 int
747 device_script(program, in, out)
748     char *program;
749     int in, out;
750 {
751     int pid;
752     int status;
753     sigset_t mask;
754
755     sigemptyset(&mask);
756     sigaddset(&mask, SIGINT);
757     sigaddset(&mask, SIGHUP);
758     sigprocmask(SIG_BLOCK, &mask, &mask);
759
760     pid = fork();
761
762     if (pid < 0) {
763         syslog(LOG_ERR, "Failed to create child process: %m");
764         die(1);
765     }
766
767     if (pid == 0) {
768         setreuid(getuid(), getuid());
769         setregid(getgid(), getgid());
770         sigprocmask(SIG_SETMASK, &mask, NULL);
771         dup2(in, 0);
772         dup2(out, 1);
773         execl("/bin/sh", "sh", "-c", program, (char *)0);
774         syslog(LOG_ERR, "could not exec /bin/sh: %m");
775         _exit(99);
776         /* NOTREACHED */
777     }
778
779     while (waitpid(pid, &status, 0) < 0) {
780         if (errno == EINTR)
781             continue;
782         syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
783         die(1);
784     }
785     sigprocmask(SIG_SETMASK, &mask, NULL);
786
787     return (status == 0 ? 0 : -1);
788 }
789
790
791 /*
792  * run-program - execute a program with given arguments,
793  * but don't wait for it.
794  * If the program can't be executed, logs an error unless
795  * must_exist is 0 and the program file doesn't exist.
796  */
797 int
798 run_program(prog, args, must_exist)
799     char *prog;
800     char **args;
801     int must_exist;
802 {
803     int pid;
804
805     pid = fork();
806     if (pid == -1) {
807         syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
808         return -1;
809     }
810     if (pid == 0) {
811         int new_fd;
812
813         /* Leave the current location */
814         (void) setsid();    /* No controlling tty. */
815         (void) umask (0);   /* no umask. Must change in script. */
816         (void) chdir ("/"); /* no current directory. */
817
818         /* Ensure that nothing of our device environment is inherited. */
819         close (0);
820         close (1);
821         close (2);
822         close (s);   /* Socket interface to the ppp device */
823         close (fd);  /* tty interface to the ppp device */
824         
825         /* Don't pass handles to the PPP device, even by accident. */
826         new_fd = open (_PATH_DEVNULL, O_RDWR);
827         if (new_fd >= 0) {
828             if (new_fd != 0) {
829                 dup2  (new_fd, 0); /* stdin <- /dev/null */
830                 close (new_fd);
831             }
832             dup2 (0, 1); /* stdout -> /dev/null */
833             dup2 (0, 2); /* stderr -> /dev/null */
834         }
835
836         /* Force the priority back to zero if pppd is running higher. */
837         if (setpriority (PRIO_PROCESS, 0, 0) < 0)
838             syslog (LOG_WARNING, "can't reset priority to 0: %m"); 
839
840         /* SysV recommends a second fork at this point. */
841
842         /* run the program */
843         execv(prog, args);
844         if (must_exist || errno != ENOENT)
845             syslog(LOG_WARNING, "Can't execute %s: %m", prog);
846         _exit(-1);
847     }
848     MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
849     ++n_children;
850     return 0;
851 }
852
853
854 /*
855  * reap_kids - get status from any dead child processes,
856  * and log a message for abnormal terminations.
857  */
858 void
859 reap_kids()
860 {
861     int pid, status;
862
863     if (n_children == 0)
864         return;
865     if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
866         if (errno != ECHILD)
867             syslog(LOG_ERR, "Error waiting for child process: %m");
868         return;
869     }
870     if (pid > 0) {
871         --n_children;
872         if (WIFSIGNALED(status)) {
873             syslog(LOG_WARNING, "Child process %d terminated with signal %d",
874                    pid, WTERMSIG(status));
875         }
876     }
877 }
878
879
880 /*
881  * log_packet - format a packet and log it.
882  */
883
884 char line[256];                 /* line to be logged accumulated here */
885 char *linep;
886
887 void
888 log_packet(p, len, prefix)
889     u_char *p;
890     int len;
891     char *prefix;
892 {
893     strcpy(line, prefix);
894     linep = line + strlen(line);
895     format_packet(p, len, pr_log, NULL);
896     if (linep != line)
897         syslog(LOG_DEBUG, "%s", line);
898 }
899
900 /*
901  * format_packet - make a readable representation of a packet,
902  * calling `printer(arg, format, ...)' to output it.
903  */
904 void
905 format_packet(p, len, printer, arg)
906     u_char *p;
907     int len;
908     void (*printer) __ARGS((void *, char *, ...));
909     void *arg;
910 {
911     int i, n;
912     u_short proto;
913     u_char x;
914
915     if (len >= DLLHEADERLEN && p[0] == ALLSTATIONS && p[1] == UI) {
916         p += 2;
917         GETSHORT(proto, p);
918         len -= DLLHEADERLEN;
919         for (i = 0; i < N_PROTO; ++i)
920             if (proto == prottbl[i].protocol)
921                 break;
922         if (i < N_PROTO) {
923             printer(arg, "[%s", prottbl[i].name);
924             n = (*prottbl[i].printpkt)(p, len, printer, arg);
925             printer(arg, "]");
926             p += n;
927             len -= n;
928         } else {
929             printer(arg, "[proto=0x%x]", proto);
930         }
931     }
932
933     for (; len > 0; --len) {
934         GETCHAR(x, p);
935         printer(arg, " %.2x", x);
936     }
937 }
938
939 #ifdef __STDC__
940 #include <stdarg.h>
941
942 void
943 pr_log(void *arg, char *fmt, ...)
944 {
945     int n;
946     va_list pvar;
947     char buf[256];
948
949     va_start(pvar, fmt);
950     vsprintf(buf, fmt, pvar);
951     va_end(pvar);
952
953     n = strlen(buf);
954     if (linep + n + 1 > line + sizeof(line)) {
955         syslog(LOG_DEBUG, "%s", line);
956         linep = line;
957     }
958     strcpy(linep, buf);
959     linep += n;
960 }
961
962 #else /* __STDC__ */
963 #include <varargs.h>
964
965 void
966 pr_log(arg, fmt, va_alist)
967 void *arg;
968 char *fmt;
969 va_dcl
970 {
971     int n;
972     va_list pvar;
973     char buf[256];
974
975     va_start(pvar);
976     vsprintf(buf, fmt, pvar);
977     va_end(pvar);
978
979     n = strlen(buf);
980     if (linep + n + 1 > line + sizeof(line)) {
981         syslog(LOG_DEBUG, "%s", line);
982         linep = line;
983     }
984     strcpy(linep, buf);
985     linep += n;
986 }
987 #endif
988
989 /*
990  * print_string - print a readable representation of a string using
991  * printer.
992  */
993 void
994 print_string(p, len, printer, arg)
995     char *p;
996     int len;
997     void (*printer) __ARGS((void *, char *, ...));
998     void *arg;
999 {
1000     int c;
1001
1002     printer(arg, "\"");
1003     for (; len > 0; --len) {
1004         c = *p++;
1005         if (' ' <= c && c <= '~')
1006             printer(arg, "%c", c);
1007         else
1008             printer(arg, "\\%.3o", c);
1009     }
1010     printer(arg, "\"");
1011 }
1012
1013 /*
1014  * novm - log an error message saying we ran out of memory, and die.
1015  */
1016 void
1017 novm(msg)
1018     char *msg;
1019 {
1020     syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
1021     die(1);
1022 }