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