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