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