]> git.ozlabs.org Git - ppp.git/blob - pppd/main.c
ea5784a2e544a595271fb8bfc441989c61fa9e7b
[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.16 1994/08/25 06:55:21 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
82 static int initfdflags = -1;    /* Initial file descriptor flags */
83
84 u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */
85 static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* buffer for incoming packet */
86
87 int hungup;                     /* terminal has been hung up */
88 static int n_children;          /* # child processes still running */
89
90 int baud_rate;
91
92 /* prototypes */
93 static void hup __ARGS((int));
94 static void term __ARGS((int));
95 static void chld __ARGS((int));
96 static void incdebug __ARGS((int));
97 static void nodebug __ARGS((int));
98
99 static void get_input __ARGS((void));
100 void establish_ppp __ARGS((void));
101 void calltimeout __ARGS((void));
102 struct timeval *timeleft __ARGS((struct timeval *));
103 void reap_kids __ARGS((void));
104 void cleanup __ARGS((int, caddr_t));
105 void close_fd __ARGS((void));
106 void die __ARGS((int));
107 void novm __ARGS((char *));
108
109 void log_packet __ARGS((u_char *, int, char *));
110 void format_packet __ARGS((u_char *, int,
111                            void (*) (void *, char *, ...), void *));
112 void pr_log __ARGS((void *, char *, ...));
113
114 extern  char    *ttyname __ARGS((int));
115 extern  char    *getlogin __ARGS((void));
116
117 /*
118  * PPP Data Link Layer "protocol" table.
119  * One entry per supported protocol.
120  */
121 static struct protent {
122     u_short protocol;
123     void (*init)();
124     void (*input)();
125     void (*protrej)();
126     int  (*printpkt)();
127     void (*datainput)();
128     char *name;
129 } prottbl[] = {
130     { LCP, lcp_init, lcp_input, lcp_protrej, lcp_printpkt, NULL, "LCP" },
131     { IPCP, ipcp_init, ipcp_input, ipcp_protrej, ipcp_printpkt, NULL, "IPCP" },
132     { UPAP, upap_init, upap_input, upap_protrej, upap_printpkt, NULL, "PAP" },
133     { CHAP, ChapInit, ChapInput, ChapProtocolReject, ChapPrintPkt, NULL, "CHAP" },
134     { CCP, ccp_init, ccp_input, ccp_protrej, ccp_printpkt, ccp_datainput, "CCP" },
135 };
136
137 #define N_PROTO         (sizeof(prottbl) / sizeof(prottbl[0]))
138
139 main(argc, argv)
140     int argc;
141     char *argv[];
142 {
143     int mask, i, nonblock;
144     struct sigaction sa;
145     struct cmd *cmdp;
146     FILE *pidfile;
147     char *p;
148     struct passwd *pw;
149     struct timeval timo;
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, incdebug);          /* Increment debug flag */
245     signal(SIGUSR2, nodebug);           /* Reset debug flag */
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", pidpath, 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             get_input();
344             reap_kids();        /* Don't leave dead kids lying around */
345         }
346
347         /*
348          * Run disconnector script, if requested
349          */
350         if (disconnector) {
351             if (device_script(disconnector, fd, fd) < 0) {
352                 syslog(LOG_WARNING, "disconnect script failed");
353                 die(1);
354             }
355
356             syslog(LOG_INFO, "Disconnected...");
357         }
358
359         close_fd();
360         if (unlink(pidfilename) < 0 && errno != ENOENT) 
361             syslog(LOG_WARNING, "unable to delete pid file: %m");
362         pidfilename[0] = 0;
363
364     } while (persist);
365
366     if (lockflag && !default_device)
367         unlock();
368
369     exit(0);
370 }
371
372
373 /*
374  * get_input - called when incoming data is available.
375  */
376 static void
377 get_input()
378 {
379     int len, i;
380     u_char *p;
381     u_short protocol;
382
383     for (;;) {                  /* Read all available packets */
384         p = inpacket_buf;       /* point to beginning of packet buffer */
385
386         len = read_packet(inpacket_buf);
387         if (len < 0)
388             return;
389
390         if (len == 0) {
391             MAINDEBUG((LOG_DEBUG, "End of file on fd!"));
392             hungup = 1;
393             lcp_lowerdown(0);   /* serial link is no longer available */
394             phase = PHASE_DEAD;
395             return;
396         }
397
398         if (debug /*&& (debugflags & DBG_INPACKET)*/)
399             log_packet(p, len, "rcvd ");
400
401         if (len < DLLHEADERLEN) {
402             MAINDEBUG((LOG_INFO, "io(): Received short packet."));
403             return;
404         }
405
406         p += 2;                         /* Skip address and control */
407         GETSHORT(protocol, p);
408         len -= DLLHEADERLEN;
409
410         /*
411          * Toss all non-LCP packets unless LCP is OPEN.
412          */
413         if (protocol != LCP && lcp_fsm[0].state != OPENED) {
414             MAINDEBUG((LOG_INFO,
415                        "io(): Received non-LCP packet when LCP not open."));
416             return;
417         }
418
419         /*
420          * Upcall the proper protocol input routine.
421          */
422         for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
423             if (prottbl[i].protocol == protocol) {
424                 (*prottbl[i].input)(0, p, len);
425                 break;
426             } else if (protocol == (prottbl[i].protocol & ~0x8000)
427                        && prottbl[i].datainput != NULL) {
428                 (*prottbl[i].datainput)(0, p, len);
429                 break;
430             }
431
432         if (i == sizeof (prottbl) / sizeof (struct protent)) {
433             if (debug)
434                 syslog(LOG_WARNING, "Unknown protocol (%x) received",
435                        protocol);
436             lcp_sprotrej(0, p - DLLHEADERLEN, len + DLLHEADERLEN);
437         }
438     }
439 }
440
441
442 /*
443  * demuxprotrej - Demultiplex a Protocol-Reject.
444  */
445 void
446 demuxprotrej(unit, protocol)
447     int unit;
448     u_short protocol;
449 {
450     int i;
451
452     /*
453      * Upcall the proper Protocol-Reject routine.
454      */
455     for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
456         if (prottbl[i].protocol == protocol) {
457             (*prottbl[i].protrej)(unit);
458             return;
459         }
460
461     syslog(LOG_WARNING,
462            "demuxprotrej: Unrecognized Protocol-Reject for protocol 0x%x",
463            protocol);
464 }
465
466
467 /*
468  * quit - Clean up state and exit.
469  */
470 void 
471 quit()
472 {
473     die(0);
474 }
475
476 /*
477  * die - like quit, except we can specify an exit status.
478  */
479 void
480 die(status)
481     int status;
482 {
483     cleanup(0, NULL);
484     syslog(LOG_INFO, "Exit.");
485     exit(status);
486 }
487
488 /*
489  * cleanup - restore anything which needs to be restored before we exit
490  */
491 /* ARGSUSED */
492 void
493 cleanup(status, arg)
494     int status;
495     caddr_t arg;
496 {
497     if (fd >= 0)
498         close_fd();
499
500     if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) 
501         syslog(LOG_WARNING, "unable to delete pid file: %m");
502     pidfilename[0] = 0;
503
504     if (lockflag && !default_device)
505         unlock();
506 }
507
508 /*
509  * close_fd - restore the terminal device and close it.
510  */
511 void
512 close_fd()
513 {
514     /* drop dtr to hang up */
515     if (modem)
516         setdtr(fd, FALSE);
517
518     if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
519         syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
520     initfdflags = -1;
521
522     disestablish_ppp();
523
524     restore_tty();
525
526     close(fd);
527     fd = -1;
528 }
529
530
531 struct  callout {
532     struct timeval      c_time;         /* time at which to call routine */
533     caddr_t             c_arg;          /* argument to routine */
534     void                (*c_func)();    /* routine */
535     struct              callout *c_next;
536 };
537
538 static struct callout *callout = NULL;  /* Callout list */
539 static struct timeval timenow;          /* Current time */
540
541 /*
542  * timeout - Schedule a timeout.
543  *
544  * Note that this timeout takes the number of seconds, NOT hz (as in
545  * the kernel).
546  */
547 void
548 timeout(func, arg, time)
549     void (*func)();
550     caddr_t arg;
551     int time;
552 {
553     struct callout *newp, *p, **pp;
554   
555     MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.",
556                (int) func, (int) arg, time));
557   
558     /*
559      * Allocate timeout.
560      */
561     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
562         syslog(LOG_ERR, "Out of memory in timeout()!");
563         die(1);
564     }
565     newp->c_arg = arg;
566     newp->c_func = func;
567     gettimeofday(&timenow, NULL);
568     newp->c_time.tv_sec = timenow.tv_sec + time;
569     newp->c_time.tv_usec = timenow.tv_usec;
570   
571     /*
572      * Find correct place and link it in.
573      */
574     for (pp = &callout; (p = *pp); pp = &p->c_next)
575         if (p->c_time.tv_sec < newp->c_time.tv_sec
576             || (p->c_time.tv_sec == newp->c_time.tv_sec
577                 && p->c_time.tv_usec <= newp->c_time.tv_sec))
578             break;
579     newp->c_next = p;
580     *pp = newp;
581 }
582
583
584 /*
585  * untimeout - Unschedule a timeout.
586  */
587 void
588 untimeout(func, arg)
589     void (*func)();
590     caddr_t arg;
591 {
592     struct itimerval itv;
593     struct callout **copp, *freep;
594     int reschedule = 0;
595   
596     MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg));
597   
598     /*
599      * Find first matching timeout and remove it from the list.
600      */
601     for (copp = &callout; (freep = *copp); copp = &freep->c_next)
602         if (freep->c_func == func && freep->c_arg == arg) {
603             *copp = freep->c_next;
604             (void) free((char *) freep);
605             break;
606         }
607 }
608
609
610 /*
611  * calltimeout - Call any timeout routines which are now due.
612  */
613 void
614 calltimeout()
615 {
616     struct callout *p;
617
618     while (callout != NULL) {
619         p = callout;
620
621         if (gettimeofday(&timenow, NULL) < 0) {
622             syslog(LOG_ERR, "Failed to get time of day: %m");
623             die(1);
624         }
625         if (!(p->c_time.tv_sec < timenow.tv_sec
626               || (p->c_time.tv_sec == timenow.tv_sec
627                   && p->c_time.tv_usec <= timenow.tv_usec)))
628             break;              /* no, it's not time yet */
629
630         callout = p->c_next;
631         (*p->c_func)(p->c_arg);
632
633         free((char *) p);
634     }
635 }
636
637
638 /*
639  * timeleft - return the length of time until the next timeout is due.
640  */
641 struct timeval *
642 timeleft(tvp)
643     struct timeval *tvp;
644 {
645     if (callout == NULL)
646         return NULL;
647
648     gettimeofday(&timenow, NULL);
649     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
650     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
651     if (tvp->tv_usec < 0) {
652         tvp->tv_usec += 1000000;
653         tvp->tv_sec -= 1;
654     }
655     if (tvp->tv_sec < 0)
656         tvp->tv_sec = tvp->tv_usec = 0;
657
658     return tvp;
659 }
660     
661
662 /*
663  * hup - Catch SIGHUP signal.
664  *
665  * Indicates that the physical layer has been disconnected.
666  * We don't rely on this indication; if the user has sent this
667  * signal, we just take the link down.
668  */
669 static void
670 hup(sig)
671     int sig;
672 {
673     syslog(LOG_INFO, "Hangup (SIGHUP)");
674     kill_link = 1;
675 }
676
677
678 /*
679  * term - Catch SIGTERM signal and SIGINT signal (^C/del).
680  *
681  * Indicates that we should initiate a graceful disconnect and exit.
682  */
683 /*ARGSUSED*/
684 static void
685 term(sig)
686     int sig;
687 {
688     syslog(LOG_INFO, "Terminating on signal %d.", sig);
689     persist = 0;                /* don't try to restart */
690     kill_link = 1;
691 }
692
693
694 /*
695  * chld - Catch SIGCHLD signal.
696  * Calls reap_kids to get status for any dead kids.
697  */
698 static void
699 chld(sig)
700     int sig;
701 {
702     reap_kids();
703 }
704
705
706 /*
707  * incdebug - Catch SIGUSR1 signal.
708  *
709  * Increment debug flag.
710  */
711 /*ARGSUSED*/
712 static void
713 incdebug(sig)
714     int sig;
715 {
716     debug++;
717     note_debug_level();
718 }
719
720
721 /*
722  * nodebug - Catch SIGUSR2 signal.
723  *
724  * Turn off debugging.
725  */
726 /*ARGSUSED*/
727 static void
728 nodebug(sig)
729     int sig;
730 {
731     debug = 0;
732     note_debug_level();
733 }
734
735
736 /*
737  * device_script - run a program to connect or disconnect the
738  * serial device.
739  */
740 int
741 device_script(program, in, out)
742     char *program;
743     int in, out;
744 {
745     int pid;
746     int status;
747     sigset_t mask;
748
749     sigemptyset(&mask);
750     sigaddset(&mask, SIGINT);
751     sigaddset(&mask, SIGHUP);
752     sigprocmask(SIG_BLOCK, &mask, &mask);
753
754     pid = fork();
755
756     if (pid < 0) {
757         syslog(LOG_ERR, "Failed to create child process: %m");
758         die(1);
759     }
760
761     if (pid == 0) {
762         setreuid(getuid(), getuid());
763         setregid(getgid(), getgid());
764         sigprocmask(SIG_SETMASK, &mask, NULL);
765         dup2(in, 0);
766         dup2(out, 1);
767         execl("/bin/sh", "sh", "-c", program, (char *)0);
768         syslog(LOG_ERR, "could not exec /bin/sh: %m");
769         _exit(99);
770         /* NOTREACHED */
771     }
772
773     while (waitpid(pid, &status, 0) < 0) {
774         if (errno == EINTR)
775             continue;
776         syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
777         die(1);
778     }
779     sigprocmask(SIG_SETMASK, &mask, NULL);
780
781     return (status == 0 ? 0 : -1);
782 }
783
784
785 /*
786  * run-program - execute a program with given arguments,
787  * but don't wait for it.
788  * If the program can't be executed, logs an error unless
789  * must_exist is 0 and the program file doesn't exist.
790  */
791 int
792 run_program(prog, args, must_exist)
793     char *prog;
794     char **args;
795     int must_exist;
796 {
797     int pid;
798
799     pid = fork();
800     if (pid == -1) {
801         syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
802         return -1;
803     }
804     if (pid == 0) {
805         int new_fd;
806
807         /* Leave the current location */
808         (void) setsid();    /* No controlling tty. */
809         (void) umask (0);   /* no umask. Must change in script. */
810         (void) chdir ("/"); /* no current directory. */
811
812         /* Ensure that nothing of our device environment is inherited. */
813         close (0);
814         close (1);
815         close (2);
816         close (s);   /* Socket interface to the ppp device */
817         close (fd);  /* tty interface to the ppp device */
818         
819         /* Don't pass handles to the PPP device, even by accident. */
820         new_fd = open (_PATH_DEVNULL, O_RDWR);
821         if (new_fd >= 0) {
822             if (new_fd != 0) {
823                 dup2  (new_fd, 0); /* stdin <- /dev/null */
824                 close (new_fd);
825             }
826             dup2 (0, 1); /* stdout -> /dev/null */
827             dup2 (0, 2); /* stderr -> /dev/null */
828         }
829
830         /* Force the priority back to zero if pppd is running higher. */
831         if (setpriority (PRIO_PROCESS, 0, 0) < 0)
832             syslog (LOG_WARNING, "can't reset priority to 0: %m"); 
833
834         /* SysV recommends a second fork at this point. */
835
836         /* run the program */
837         execv(prog, args);
838         if (must_exist || errno != ENOENT)
839             syslog(LOG_WARNING, "Can't execute %s: %m", prog);
840         _exit(-1);
841     }
842     MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
843     ++n_children;
844     return 0;
845 }
846
847
848 /*
849  * reap_kids - get status from any dead child processes,
850  * and log a message for abnormal terminations.
851  */
852 void
853 reap_kids()
854 {
855     int pid, status;
856
857     if (n_children == 0)
858         return;
859     if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
860         if (errno != ECHILD)
861             syslog(LOG_ERR, "Error waiting for child process: %m");
862         return;
863     }
864     if (pid > 0) {
865         --n_children;
866         if (WIFSIGNALED(status)) {
867             syslog(LOG_WARNING, "Child process %d terminated with signal %d",
868                    pid, WTERMSIG(status));
869         }
870     }
871 }
872
873
874 /*
875  * log_packet - format a packet and log it.
876  */
877
878 char line[256];                 /* line to be logged accumulated here */
879 char *linep;
880
881 void
882 log_packet(p, len, prefix)
883     u_char *p;
884     int len;
885     char *prefix;
886 {
887     strcpy(line, prefix);
888     linep = line + strlen(line);
889     format_packet(p, len, pr_log, NULL);
890     if (linep != line)
891         syslog(LOG_DEBUG, "%s", line);
892 }
893
894 /*
895  * format_packet - make a readable representation of a packet,
896  * calling `printer(arg, format, ...)' to output it.
897  */
898 void
899 format_packet(p, len, printer, arg)
900     u_char *p;
901     int len;
902     void (*printer) __ARGS((void *, char *, ...));
903     void *arg;
904 {
905     int i, n;
906     u_short proto;
907     u_char x;
908
909     if (len >= DLLHEADERLEN && p[0] == ALLSTATIONS && p[1] == UI) {
910         p += 2;
911         GETSHORT(proto, p);
912         len -= DLLHEADERLEN;
913         for (i = 0; i < N_PROTO; ++i)
914             if (proto == prottbl[i].protocol)
915                 break;
916         if (i < N_PROTO) {
917             printer(arg, "[%s", prottbl[i].name);
918             n = (*prottbl[i].printpkt)(p, len, printer, arg);
919             printer(arg, "]");
920             p += n;
921             len -= n;
922         } else {
923             printer(arg, "[proto=0x%x]", proto);
924         }
925     }
926
927     for (; len > 0; --len) {
928         GETCHAR(x, p);
929         printer(arg, " %.2x", x);
930     }
931 }
932
933 #ifdef __STDC__
934 #include <stdarg.h>
935
936 void
937 pr_log(void *arg, char *fmt, ...)
938 {
939     int n;
940     va_list pvar;
941     char buf[256];
942
943     va_start(pvar, fmt);
944     vsprintf(buf, fmt, pvar);
945     va_end(pvar);
946
947     n = strlen(buf);
948     if (linep + n + 1 > line + sizeof(line)) {
949         syslog(LOG_DEBUG, "%s", line);
950         linep = line;
951     }
952     strcpy(linep, buf);
953     linep += n;
954 }
955
956 #else /* __STDC__ */
957 #include <varargs.h>
958
959 void
960 pr_log(arg, fmt, va_alist)
961 void *arg;
962 char *fmt;
963 va_dcl
964 {
965     int n;
966     va_list pvar;
967     char buf[256];
968
969     va_start(pvar);
970     vsprintf(buf, fmt, pvar);
971     va_end(pvar);
972
973     n = strlen(buf);
974     if (linep + n + 1 > line + sizeof(line)) {
975         syslog(LOG_DEBUG, "%s", line);
976         linep = line;
977     }
978     strcpy(linep, buf);
979     linep += n;
980 }
981 #endif
982
983 /*
984  * print_string - print a readable representation of a string using
985  * printer.
986  */
987 void
988 print_string(p, len, printer, arg)
989     char *p;
990     int len;
991     void (*printer) __ARGS((void *, char *, ...));
992     void *arg;
993 {
994     int c;
995
996     printer(arg, "\"");
997     for (; len > 0; --len) {
998         c = *p++;
999         if (' ' <= c && c <= '~')
1000             printer(arg, "%c", c);
1001         else
1002             printer(arg, "\\%.3o", c);
1003     }
1004     printer(arg, "\"");
1005 }
1006
1007 /*
1008  * novm - log an error message saying we ran out of memory, and die.
1009  */
1010 void
1011 novm(msg)
1012     char *msg;
1013 {
1014     syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
1015     die(1);
1016 }