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