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