]> git.ozlabs.org Git - ppp.git/blob - pppd/main.c
fail if /etc/ppp/options not present if -DREQ_SYSOPTIONS=1
[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.2 1993/11/23 23:40:53 paulus Exp $";
22 #endif
23
24 #define SETSID
25
26 #include <stdio.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
34 /*
35  * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless
36  * /etc/ppp/options exists.
37  */
38 #ifndef REQ_SYSOPTIONS
39 #define REQ_SYSOPTIONS  0
40 #endif
41
42 #ifdef STREAMS
43 #undef SGTTY
44 #endif
45
46 #ifdef SGTTY
47 #include <sgtty.h>
48 #else
49 #ifndef sun
50 #include <sys/ioctl.h>
51 #endif
52 #include <termios.h>
53 #endif
54
55 #include <sys/param.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <sys/socket.h>
59 #include <sys/time.h>
60
61 #include "callout.h"
62
63 #include <net/if.h>
64 #include <net/if_ppp.h>
65
66 #include <string.h>
67
68 #ifndef BSD
69 #define BSD 43
70 #endif /*BSD*/
71
72 #include "ppp.h"
73 #include "magic.h"
74 #include "fsm.h"
75 #include "lcp.h"
76 #include "ipcp.h"
77 #include "upap.h"
78 #include "chap.h"
79
80 #include "pppd.h"
81 #include "pathnames.h"
82 #include "patchlevel.h"
83
84
85 #ifndef TRUE
86 #define TRUE (1)
87 #endif /*TRUE*/
88
89 #ifndef FALSE
90 #define FALSE (0)
91 #endif /*FALSE*/
92
93 #ifdef PIDPATH
94 static char *pidpath = PIDPATH; /* filename in which pid will be stored */
95 #else
96 static char *pidpath = _PATH_PIDFILE;
97 #endif /* PIDFILE */
98
99 /* interface vars */
100 char ifname[IFNAMSIZ];          /* Interface name */
101 int ifunit;                     /* Interface unit number */
102
103 char *progname;                 /* Name of this program */
104 char hostname[MAXNAMELEN];      /* Our hostname */
105 char our_name[MAXNAMELEN];
106 char remote_name[MAXNAMELEN];
107
108 static pid_t    pid;            /* Our pid */
109 static pid_t    pgrpid;         /* Process Group ID */
110 static char pidfilename[MAXPATHLEN];
111
112 char devname[MAXPATHLEN] = "/dev/tty";  /* Device name */
113 int default_device = TRUE;      /* use default device (stdin/out) */
114
115 int fd;                         /* Device file descriptor */
116 int s;                          /* Socket file descriptor */
117
118 #ifdef SGTTY
119 static struct sgttyb initsgttyb;        /* Initial TTY sgttyb */
120 #else
121 static struct termios inittermios;      /* Initial TTY termios */
122 #endif
123
124 static int initfdflags = -1;    /* Initial file descriptor flags */
125
126 static int restore_term;        /* 1 => we've munged the terminal */
127
128 u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */
129 static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* buffer for incoming packet */
130
131 int hungup;                     /* terminal has been hung up */
132
133 /* configured variables */
134
135 int debug = 0;                  /* Debug flag */
136 char user[MAXNAMELEN];          /* username for PAP */
137 char passwd[MAXSECRETLEN];      /* password for PAP */
138 char *connector = NULL;         /* "connect" command */
139 int inspeed = 0;                /* Input/Output speed */
140 u_long netmask = 0;             /* netmask to use on ppp interface */
141 int crtscts = 0;                /* use h/w flow control */
142 int nodetach = 0;               /* don't fork */
143 int modem = 0;                  /* use modem control lines */
144 int auth_required = 0;          /* require peer to authenticate */
145 int defaultroute = 0;           /* assign default route through interface */
146 int proxyarp = 0;               /* set entry in arp table */
147 int persist = 0;                /* re-initiate on termination */
148 int answer = 0;                 /* wait for incoming call */
149 int uselogin = 0;               /* check PAP info against /etc/passwd */
150
151
152 /* prototypes */
153 static void hup __ARGS((int, int, struct sigcontext *, char *));
154 static void intr __ARGS((int, int, struct sigcontext *, char *));
155 static void term __ARGS((int, int, struct sigcontext *, char *));
156 static void alrm __ARGS((int, int, struct sigcontext *, char *));
157 static void io __ARGS((int, int, struct sigcontext *, char *));
158 static void incdebug __ARGS((int));
159 static void nodebug __ARGS((int));
160 void establish_ppp __ARGS((void));
161
162 void cleanup __ARGS((int, caddr_t));
163 void die __ARGS((int));
164 void dumpbuffer __ARGS((unsigned char *, int, int));
165
166 #ifdef  STREAMS
167 extern  char    *ttyname __ARGS((int));
168 #endif
169 extern  char    *getlogin __ARGS((void));
170
171 /*
172  * PPP Data Link Layer "protocol" table.
173  * One entry per supported protocol.
174  */
175 static struct protent {
176     u_short protocol;
177     void (*init)();
178     void (*input)();
179     void (*protrej)();
180 } prottbl[] = {
181     { LCP, lcp_init, lcp_input, lcp_protrej },
182     { IPCP, ipcp_init, ipcp_input, ipcp_protrej },
183     { UPAP, upap_init, upap_input, upap_protrej },
184     { CHAP, ChapInit, ChapInput, ChapProtocolReject },
185 };
186
187
188 main(argc, argv)
189     int argc;
190     char *argv[];
191 {
192     int mask, i;
193     struct sigvec sv;
194     struct cmd *cmdp;
195     FILE *pidfile;
196     char *p;
197
198     /*
199      * Initialize syslog system and magic number package.
200      */
201 #if BSD >= 43 || defined(sun)
202     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
203     setlogmask(LOG_UPTO(LOG_INFO));
204 #else
205     openlog("pppd", LOG_PID);
206 #define LOG_UPTO(x) (x)
207 #define setlogmask(x) (x)
208 #endif
209
210 #ifdef STREAMS
211     p = ttyname(fileno(stdin));
212     if (p)
213         strcpy(devname, p);
214 #endif
215   
216     magic_init();
217
218     if (gethostname(hostname, MAXNAMELEN) < 0 ) {
219         syslog(LOG_ERR, "couldn't get hostname: %m");
220         die(1);
221     }
222     hostname[MAXNAMELEN-1] = 0;
223
224     pid = getpid();
225
226     /*
227      * Initialize to the standard option set, then parse, in order,
228      * the system options file, the user's options file, and the command
229      * line arguments.
230      */
231     for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
232         (*prottbl[i].init)(0);
233   
234     progname = *argv;
235
236     if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS) ||
237         !options_from_user() ||
238         !parse_args(argc-1, argv+1))
239         die(1);
240     check_auth_options();
241     setipdefault();
242
243     p = getlogin();
244     if (p == NULL)
245         p = "(unknown)";
246     syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d",
247            VERSION, PATCHLEVEL, p, getuid());
248
249 #ifdef SETSID
250     /*
251      * Make sure we can set the serial device to be our controlling terminal.
252      */
253     if (default_device) {
254         /*
255          * No device name was specified:
256          * we are in the device's session already.
257          */
258         if ((pgrpid = getpgrp(0)) < 0) {
259             syslog(LOG_ERR, "getpgrp(0): %m");
260             die(1);
261         }
262         if (pgrpid != pid) 
263             syslog(LOG_WARNING, "warning... not a process group leader");
264
265     } else {
266         /*
267          * Not default device: make sure we're not a process group leader,
268          * then become session leader of a new session (so we can make
269          * our device its controlling terminal and thus get SIGHUPs).
270          */
271         if (!nodetach) {
272             /* fork so we're not a process group leader */
273             if (pid = fork()) {
274                 exit(0);        /* parent is finished */
275             }
276             if (pid < 0) {
277                 syslog(LOG_ERR, "fork: %m");
278                 die(1);
279             }
280             pid = getpid();     /* otherwise pid is 0 in child */
281         } else {
282             /*
283              * try to put ourself into our parent's process group,
284              * so we're not a process group leader
285              */
286             if (setpgrp(pid, getppid()) < 0)
287                 syslog(LOG_WARNING, "setpgrp: %m");
288         }
289
290         /* create new session */
291         if ((pgrpid = setsid()) < 0) {
292             syslog(LOG_ERR, "setsid(): %m");
293             die(1);
294         }
295     }
296 #endif
297
298     /* Get an internet socket for doing socket ioctl's on. */
299     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
300         syslog(LOG_ERR, "socket : %m");
301         die(1);
302     }
303   
304     /*
305      * Compute mask of all interesting signals and install signal handlers
306      * for each.  Only one signal handler may be active at a time.  Therefore,
307      * all other signals should be masked when any handler is executing.
308      */
309     sigemptyset(&mask);
310     sigaddset(&mask, SIGHUP);
311     sigaddset(&mask, SIGINT);
312     sigaddset(&mask, SIGALRM);
313     sigaddset(&mask, SIGIO);
314 #ifdef  STREAMS
315     sigaddset(&mask, SIGPOLL);
316 #endif
317
318 #define SIGNAL(s, handler)      { \
319         sv.sv_handler = handler; \
320         if (sigvec(s, &sv, NULL) < 0) { \
321             syslog(LOG_ERR, "sigvec(%d): %m", s); \
322             die(1); \
323         } \
324     }
325
326     sv.sv_mask = mask;
327     sv.sv_flags = 0;
328     SIGNAL(SIGHUP, hup);                /* Hangup */
329     SIGNAL(SIGINT, intr);               /* Interrupt */
330     SIGNAL(SIGTERM, term);              /* Terminate */
331     SIGNAL(SIGALRM, alrm);              /* Timeout */
332     SIGNAL(SIGIO, io);                  /* Input available */
333 #ifdef  STREAMS
334     SIGNAL(SIGPOLL, io);                /* Input available */
335 #endif
336
337     signal(SIGUSR1, incdebug);          /* Increment debug flag */
338     signal(SIGUSR2, nodebug);           /* Reset debug flag */
339   
340
341     /*
342      * Open the serial device and set it up to be the ppp interface.
343      */
344     if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) {
345         syslog(LOG_ERR, "open(%s): %m", devname);
346         die(1);
347     }
348     hungup = 0;
349
350     /* set device to be controlling tty */
351     if (!default_device && ioctl(fd, TIOCSCTTY) < 0) {
352         syslog(LOG_ERR, "ioctl(TIOCSCTTY): %m");
353         die(1);
354     }
355
356     /* set line speed, flow control, etc. */
357     set_up_tty(fd);
358
359     /* run connection script */
360     if (connector) {
361         syslog(LOG_INFO, "Connecting with <%s>", connector);
362
363         /* drop dtr to hang up in case modem is off hook */
364         if (!default_device && modem) {
365             setdtr(fd, FALSE);
366             sleep(1);
367             setdtr(fd, TRUE);
368         }
369
370         if (set_up_connection(connector, fd, fd) < 0) {
371             syslog(LOG_ERR, "could not set up connection");
372             setdtr(fd, FALSE);
373             die(1);
374         }
375
376         syslog(LOG_INFO, "Connected...");
377         sleep(1);               /* give it time to set up its terminal */
378     }
379   
380     /* set up the serial device as a ppp interface */
381     establish_ppp();
382
383     syslog(LOG_INFO, "Using interface ppp%d", ifunit);
384     (void) sprintf(ifname, "ppp%d", ifunit);
385
386     /* write pid to file */
387     (void) sprintf(pidfilename, "%s/%s.pid", pidpath, ifname);
388     if ((pidfile = fopen(pidfilename, "w")) != NULL) {
389         fprintf(pidfile, "%d\n", pid);
390         (void) fclose(pidfile);
391     } else {
392         syslog(LOG_ERR, "unable to create pid file: %m");
393         pidfilename[0] = 0;
394     }
395
396     /*
397      * Set process group of device to our process group so we can get SIGIOs.
398      */
399 #ifdef SETSID
400     if (default_device) {
401         int id = tcgetpgrp(fd);
402         if (id != pgrpid) {
403             syslog(LOG_WARNING,
404                    "warning: not foreground process group leader");
405         }
406     } else {
407         if (tcsetpgrp(fd, pgrpid) < 0) {
408             syslog(LOG_ERR, "tcsetpgrp(): %m");
409             die(1);
410         }
411     }
412 #else
413     /* set process group on tty so we get SIGIO's */
414     if (ioctl(fd, TIOCSPGRP, &pgrpid) < 0) {
415         syslog(LOG_ERR, "ioctl(TIOCSPGRP): %m");
416         die(1);
417     }
418 #endif
419
420     /*
421      * Record initial device flags, then set device to cause SIGIO
422      * signals to be generated.
423      */
424     if ((initfdflags = fcntl(fd, F_GETFL)) == -1) {
425         syslog(LOG_ERR, "fcntl(F_GETFL): %m");
426         die(1);
427     }
428     if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) {
429         syslog(LOG_ERR, "fcntl(F_SETFL, FNDELAY | FASYNC): %m");
430         die(1);
431     }
432   
433     /*
434      * Block all signals, start opening the connection, and  wait for
435      * incoming signals (reply, timeout, etc.).
436      */
437     syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devname);
438     sigprocmask(SIG_BLOCK, &mask, NULL); /* Block signals now */
439     lcp_lowerup(0);                     /* XXX Well, sort of... */
440     lcp_open(0);                        /* Start protocol */
441     for (;;) {
442         sigpause(0);                    /* Wait for next signal */
443     }
444 }
445
446 #if B9600 == 9600
447 /*
448  * XXX assume speed_t values numerically equal bits per second
449  * (so we can ask for any speed).
450  */
451 #define translate_speed(bps)    (bps)
452
453 #else
454 /*
455  * List of valid speeds.
456  */
457 struct speed {
458     int speed_int, speed_val;
459 } speeds[] = {
460 #ifdef B50
461     { 50, B50 },
462 #endif
463 #ifdef B75
464     { 75, B75 },
465 #endif
466 #ifdef B110
467     { 110, B110 },
468 #endif
469 #ifdef B134
470     { 134, B134 },
471 #endif
472 #ifdef B150
473     { 150, B150 },
474 #endif
475 #ifdef B200
476     { 200, B200 },
477 #endif
478 #ifdef B300
479     { 300, B300 },
480 #endif
481 #ifdef B600
482     { 600, B600 },
483 #endif
484 #ifdef B1200
485     { 1200, B1200 },
486 #endif
487 #ifdef B1800
488     { 1800, B1800 },
489 #endif
490 #ifdef B2000
491     { 2000, B2000 },
492 #endif
493 #ifdef B2400
494     { 2400, B2400 },
495 #endif
496 #ifdef B3600
497     { 3600, B3600 },
498 #endif
499 #ifdef B4800
500     { 4800, B4800 },
501 #endif
502 #ifdef B7200
503     { 7200, B7200 },
504 #endif
505 #ifdef B9600
506     { 9600, B9600 },
507 #endif
508 #ifdef B19200
509     { 19200, B19200 },
510 #endif
511 #ifdef B38400
512     { 38400, B38400 },
513 #endif
514 #ifdef EXTA
515     { 19200, EXTA },
516 #endif
517 #ifdef EXTB
518     { 38400, EXTB },
519 #endif
520 #ifdef B57600
521     { 57600, B57600 },
522 #endif
523 #ifdef B115200
524     { 115200, B115200 },
525 #endif
526     { 0, 0 }
527 };
528
529 /*
530  * Translate from bits/second to a speed_t.
531  */
532 int
533 translate_speed(bps)
534     int bps;
535 {
536     struct speed *speedp;
537
538     if (bps == 0)
539         return 0;
540     for (speedp = speeds; speedp->speed_int; speedp++)
541         if (bps == speedp->speed_int)
542             return speedp->speed_val;
543     syslog(LOG_WARNING, "speed %d not supported", bps);
544     return 0;
545 }
546 #endif
547
548 /*
549  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
550  * at the requested speed, etc.
551  */
552 set_up_tty(fd)
553     int fd;
554 {
555 #ifndef SGTTY
556     int speed;
557     struct termios tios;
558
559     if (tcgetattr(fd, &tios) < 0) {
560         syslog(LOG_ERR, "tcgetattr: %m");
561         die(1);
562     }
563
564     if (!restore_term)
565         inittermios = tios;
566
567     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL | CRTSCTS);
568     tios.c_cflag |= CS8 | CREAD | HUPCL;
569     if (crtscts)
570         tios.c_cflag |= CRTSCTS;
571     if (!modem)
572         tios.c_cflag |= CLOCAL;
573     tios.c_iflag = IGNBRK | IGNPAR;
574     tios.c_oflag = 0;
575     tios.c_lflag = 0;
576     tios.c_cc[VMIN] = 1;
577     tios.c_cc[VTIME] = 0;
578     speed = translate_speed(inspeed);
579     if (speed) {
580         cfsetospeed(&tios, speed);
581         cfsetispeed(&tios, speed);
582     }
583
584     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
585         syslog(LOG_ERR, "tcsetattr: %m");
586         die(1);
587     }
588 #else   /* SGTTY */
589     int speed;
590     struct sgttyb sgttyb;
591
592     /*
593      * Put the tty in raw mode.
594      */
595     if (ioctl(fd, TIOCGETP, &sgttyb) < 0) {
596         syslog(LOG_ERR, "ioctl(TIOCGETP): %m");
597         die(1);
598     }
599
600     if (!restore_term)
601         initsgttyb = sgttyb;
602
603     sgttyb.sg_flags = RAW | ANYP;
604     speed = translate_speed(inspeed);
605     if (speed)
606         sgttyb.sg_ispeed = speed;
607
608     if (ioctl(fd, TIOCSETP, &sgttyb) < 0) {
609         syslog(LOG_ERR, "ioctl(TIOCSETP): %m");
610         die(1);
611     }
612 #endif
613     restore_term = TRUE;
614 }
615
616
617 /*
618  * quit - Clean up state and exit.
619  */
620 void 
621 quit()
622 {
623     die(0);
624 }
625
626 /*
627  * die - like quit, except we can specify an exit status.
628  */
629 void
630 die(status)
631     int status;
632 {
633     cleanup(0, NULL);
634     syslog(LOG_INFO, "Exit.");
635     exit(status);
636 }
637
638 /*
639  * cleanup - restore anything which needs to be restored before we exit
640  */
641 /* ARGSUSED */
642 void
643 cleanup(status, arg)
644     int status;
645     caddr_t arg;
646 {
647     if (fd != 0) {
648         /* drop dtr to hang up */
649         if (modem)
650             setdtr(fd, FALSE);
651
652         if (fcntl(fd, F_SETFL, initfdflags) < 0)
653             syslog(LOG_ERR, "fcntl(F_SETFL, fdflags): %m");
654
655         disestablish_ppp();
656
657         if (restore_term) {
658 #ifndef SGTTY
659             if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
660                 syslog(LOG_ERR, "tcsetattr: %m");
661 #else
662             if (ioctl(fd, TIOCSETP, &initsgttyb) < 0)
663                 syslog(LOG_ERR, "ioctl(TIOCSETP): %m");
664 #endif
665         }
666
667         close(fd);
668         fd = 0;
669     }
670
671     if (pidfilename[0] != 0 && unlink(pidfilename) < 0) 
672         syslog(LOG_WARNING, "unable to unlink pid file: %m");
673     pidfilename[0] = 0;
674 }
675
676
677 static struct callout *callout = NULL;          /* Callout list */
678 static struct timeval schedtime;                /* Time last timeout was set */
679
680 /*
681  * timeout - Schedule a timeout.
682  *
683  * Note that this timeout takes the number of seconds, NOT hz (as in
684  * the kernel).
685  */
686 void
687 timeout(func, arg, time)
688     void (*func)();
689     caddr_t arg;
690     int time;
691 {
692     struct itimerval itv;
693     struct callout *newp, **oldpp;
694   
695     MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.",
696                (int) func, (int) arg, time));
697   
698     /*
699      * Allocate timeout.
700      */
701     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
702         syslog(LOG_ERR, "Out of memory in timeout()!");
703         die(1);
704     }
705     newp->c_arg = arg;
706     newp->c_func = func;
707   
708     /*
709      * Find correct place to link it in and decrement its time by the
710      * amount of time used by preceding timeouts.
711      */
712     for (oldpp = &callout;
713          *oldpp && (*oldpp)->c_time <= time;
714          oldpp = &(*oldpp)->c_next)
715         time -= (*oldpp)->c_time;
716     newp->c_time = time;
717     newp->c_next = *oldpp;
718     if (*oldpp)
719         (*oldpp)->c_time -= time;
720     *oldpp = newp;
721   
722     /*
723      * If this is now the first callout then we have to set a new
724      * itimer.
725      */
726     if (callout == newp) {
727         itv.it_interval.tv_sec = itv.it_interval.tv_usec =
728             itv.it_value.tv_usec = 0;
729         itv.it_value.tv_sec = callout->c_time;
730         MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds.",
731                    itv.it_value.tv_sec));
732         if (setitimer(ITIMER_REAL, &itv, NULL)) {
733             syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m");
734             die(1);
735         }
736         if (gettimeofday(&schedtime, NULL)) {
737             syslog(LOG_ERR, "gettimeofday: %m");
738             die(1);
739         }
740     }
741 }
742
743
744 /*
745  * untimeout - Unschedule a timeout.
746  */
747 void
748 untimeout(func, arg)
749     void (*func)();
750     caddr_t arg;
751 {
752     struct itimerval itv;
753     struct callout **copp, *freep;
754     int reschedule = 0;
755   
756     MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg));
757   
758     /*
759      * If the first callout is unscheduled then we have to set a new
760      * itimer.
761      */
762     if (callout &&
763         callout->c_func == func &&
764         callout->c_arg == arg)
765         reschedule = 1;
766   
767     /*
768      * Find first matching timeout.  Add its time to the next timeouts
769      * time.
770      */
771     for (copp = &callout; *copp; copp = &(*copp)->c_next)
772         if ((*copp)->c_func == func &&
773             (*copp)->c_arg == arg) {
774             freep = *copp;
775             *copp = freep->c_next;
776             if (*copp)
777                 (*copp)->c_time += freep->c_time;
778             (void) free((char *) freep);
779             break;
780         }
781   
782     if (reschedule) {
783         itv.it_interval.tv_sec = itv.it_interval.tv_usec =
784             itv.it_value.tv_usec = 0;
785         itv.it_value.tv_sec = callout ? callout->c_time : 0;
786         MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds.",
787                    itv.it_value.tv_sec));
788         if (setitimer(ITIMER_REAL, &itv, NULL)) {
789             syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m");
790             die(1);
791         }
792         if (gettimeofday(&schedtime, NULL)) {
793             syslog(LOG_ERR, "gettimeofday: %m");
794             die(1);
795         }
796     }
797 }
798
799
800 /*
801  * adjtimeout - Decrement the first timeout by the amount of time since
802  * it was scheduled.
803  */
804 void
805 adjtimeout()
806 {
807     struct timeval tv;
808     int timediff;
809   
810     if (callout == NULL)
811         return;
812     /*
813      * Make sure that the clock hasn't been warped dramatically.
814      * Account for recently expired, but blocked timer by adding
815      * small fudge factor.
816      */
817     if (gettimeofday(&tv, NULL)) {
818         syslog(LOG_ERR, "gettimeofday: %m");
819         die(1);
820     }
821     timediff = tv.tv_sec - schedtime.tv_sec;
822     if (timediff < 0 ||
823         timediff > callout->c_time + 1)
824         return;
825   
826     callout->c_time -= timediff;        /* OK, Adjust time */
827 }
828
829
830 /*
831  * hup - Catch SIGHUP signal.
832  *
833  * Indicates that the physical layer has been disconnected.
834  */
835 /*ARGSUSED*/
836 static void
837 hup(sig, code, scp, addr)
838     int sig, code;
839     struct sigcontext *scp;
840     char *addr;
841 {
842     syslog(LOG_INFO, "Hangup (SIGHUP)");
843
844     hungup = 1;                 /* they hung up on us! */
845     persist = 0;                /* don't try to restart */
846     adjtimeout();               /* Adjust timeouts */
847     lcp_lowerdown(0);           /* Reset connection */
848     quit();                     /* and die */
849 }
850
851
852 /*
853  * term - Catch SIGTERM signal.
854  *
855  * Indicates that we should initiate a graceful disconnect and exit.
856  */
857 /*ARGSUSED*/
858 static void
859 term(sig, code, scp, addr)
860     int sig, code;
861     struct sigcontext *scp;
862     char *addr;
863 {
864     syslog(LOG_INFO, "Terminating link.");
865     persist = 0;                /* don't try to restart */
866     adjtimeout();               /* Adjust timeouts */
867     lcp_close(0);               /* Close connection */
868 }
869
870
871 /*
872  * intr - Catch SIGINT signal (DEL/^C).
873  *
874  * Indicates that we should initiate a graceful disconnect and exit.
875  */
876 /*ARGSUSED*/
877 static void
878 intr(sig, code, scp, addr)
879     int sig, code;
880     struct sigcontext *scp;
881     char *addr;
882 {
883     syslog(LOG_INFO, "Interrupt received: terminating link");
884     persist = 0;                /* don't try to restart */
885     adjtimeout();               /* Adjust timeouts */
886     lcp_close(0);               /* Close connection */
887 }
888
889
890 /*
891  * alrm - Catch SIGALRM signal.
892  *
893  * Indicates a timeout.
894  */
895 /*ARGSUSED*/
896 static void
897 alrm(sig, code, scp, addr)
898     int sig, code;
899     struct sigcontext *scp;
900     char *addr;
901 {
902     struct itimerval itv;
903     struct callout *freep;
904
905     MAINDEBUG((LOG_DEBUG, "Alarm"));
906
907     /*
908      * Call and free first scheduled timeout and any that were scheduled
909      * for the same time.
910      */
911     while (callout) {
912         freep = callout;        /* Remove entry before calling */
913         callout = freep->c_next;
914         (*freep->c_func)(freep->c_arg);
915         (void) free((char *) freep);
916         if (callout && callout->c_time)
917             break;
918     }
919   
920     /*
921      * Set a new itimer if there are more timeouts scheduled.
922      */
923     if (callout) {
924         itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0;
925         itv.it_value.tv_usec = 0;
926         itv.it_value.tv_sec = callout->c_time;
927         MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds.",
928                    itv.it_value.tv_sec));
929         if (setitimer(ITIMER_REAL, &itv, NULL)) {
930             syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m");
931             die(1);
932         }
933         if (gettimeofday(&schedtime, NULL)) {
934             syslog(LOG_ERR, "gettimeofday: %m");
935             die(1);
936         }
937     }
938 }
939
940
941 /*
942  * io - Catch SIGIO signal.
943  *
944  * Indicates that incoming data is available.
945  */
946 /*ARGSUSED*/
947 static void
948 io(sig, code, scp, addr)
949     int sig, code;
950     struct sigcontext *scp;
951     char *addr;
952 {
953     int len, i;
954     u_char *p;
955     u_short protocol;
956     fd_set fdset;
957     struct timeval notime;
958     int ready;
959
960     MAINDEBUG((LOG_DEBUG, "IO signal received"));
961     adjtimeout();               /* Adjust timeouts */
962
963     /* we do this to see if the SIGIO handler is being invoked for input */
964     /* ready, or for the socket buffer hitting the low-water mark. */
965
966     notime.tv_sec = 0;
967     notime.tv_usec = 0;
968     FD_ZERO(&fdset);
969     FD_SET(fd, &fdset);
970   
971     if ((ready = select(32, &fdset, (fd_set *) NULL, (fd_set *) NULL,
972                       &notime)) == -1) {
973         syslog(LOG_ERR, "Error in io() select: %m");
974         die(1);
975     }
976     
977     if (ready == 0) {
978         MAINDEBUG((LOG_DEBUG, "IO non-input ready SIGIO occured."));
979         return;
980     }
981
982     /* Yup, this is for real */
983     for (;;) {                  /* Read all available packets */
984         p = inpacket_buf;       /* point to beginning of packet buffer */
985
986         len = read_packet(inpacket_buf);
987         if (len < 0)
988             return;
989
990         if (len == 0) {
991             syslog(LOG_ERR, "End of file on fd!");
992             die(1);
993         }
994
995         if (len < DLLHEADERLEN) {
996             MAINDEBUG((LOG_INFO, "io(): Received short packet."));
997             return;
998         }
999
1000         p += 2;                         /* Skip address and control */
1001         GETSHORT(protocol, p);
1002         len -= DLLHEADERLEN;
1003
1004         /*
1005          * Toss all non-LCP packets unless LCP is OPEN.
1006          */
1007         if (protocol != LCP && lcp_fsm[0].state != OPENED) {
1008             MAINDEBUG((LOG_INFO,
1009                        "io(): Received non-LCP packet when LCP not open."));
1010             if (debug)
1011                 dumpbuffer(inpacket_buf, len + DLLHEADERLEN, LOG_INFO);
1012             return;
1013         }
1014
1015         /*
1016          * Upcall the proper protocol input routine.
1017          */
1018         for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
1019             if (prottbl[i].protocol == protocol) {
1020                 (*prottbl[i].input)(0, p, len);
1021                 break;
1022             }
1023
1024         if (i == sizeof (prottbl) / sizeof (struct protent)) {
1025             syslog(LOG_WARNING, "input: Unknown protocol (%x) received!",
1026                    protocol);
1027             lcp_sprotrej(0, p - DLLHEADERLEN, len + DLLHEADERLEN);
1028         }
1029     }
1030 }
1031
1032 /*
1033  * demuxprotrej - Demultiplex a Protocol-Reject.
1034  */
1035 void
1036 demuxprotrej(unit, protocol)
1037     int unit;
1038     u_short protocol;
1039 {
1040     int i;
1041
1042     /*
1043      * Upcall the proper Protocol-Reject routine.
1044      */
1045     for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++)
1046         if (prottbl[i].protocol == protocol) {
1047             (*prottbl[i].protrej)(unit);
1048             return;
1049         }
1050
1051     syslog(LOG_WARNING,
1052            "demuxprotrej: Unrecognized Protocol-Reject for protocol %d!",
1053            protocol);
1054 }
1055
1056
1057 /*
1058  * incdebug - Catch SIGUSR1 signal.
1059  *
1060  * Increment debug flag.
1061  */
1062 /*ARGSUSED*/
1063 static void
1064 incdebug(sig)
1065     int sig;
1066 {
1067     syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
1068     setlogmask(LOG_UPTO(LOG_DEBUG));
1069     debug++;
1070 }
1071
1072
1073 /*
1074  * nodebug - Catch SIGUSR2 signal.
1075  *
1076  * Turn off debugging.
1077  */
1078 /*ARGSUSED*/
1079 static void
1080 nodebug(sig)
1081     int sig;
1082 {
1083     setlogmask(LOG_UPTO(LOG_WARNING));
1084     debug = 0;
1085 }
1086
1087
1088 /*
1089  * set_up_connection - run a program to initialize the serial connector
1090  */
1091 int
1092 set_up_connection(program, in, out)
1093     char *program;
1094     int in, out;
1095 {
1096     int pid;
1097     int status;
1098     sigset_t mask;
1099
1100     sigemptyset(&mask);
1101     sigaddset(&mask, SIGINT);
1102     sigaddset(&mask, SIGHUP);
1103     sigprocmask(SIG_BLOCK, &mask, &mask);
1104
1105     pid = fork();
1106   
1107     if (pid < 0) {
1108         syslog(LOG_ERR, "fork: %m");
1109         die(1);
1110     }
1111   
1112     if (pid == 0) {
1113         setreuid(getuid(), getuid());
1114         setregid(getgid(), getgid());
1115         sigprocmask(SIG_SETMASK, &mask, NULL);
1116         dup2(in, 0);
1117         dup2(out, 1);
1118         execl("/bin/sh", "sh", "-c", program, (char *)0);
1119         syslog(LOG_ERR, "could not exec /bin/sh: %m");
1120         _exit(99);
1121         /* NOTREACHED */
1122     }
1123
1124     while (waitpid(pid, &status, 0) != pid) {
1125         if (errno == EINTR)
1126             continue;
1127         syslog(LOG_ERR, "waiting for connection process: %m");
1128         die(1);
1129     }
1130     sigprocmask(SIG_SETMASK, &mask, NULL);
1131
1132     return (status == 0 ? 0 : -1);
1133 }
1134
1135
1136 /*
1137  * Return user specified netmask. A value of zero means no netmask has
1138  * been set. 
1139  */
1140 /* ARGSUSED */
1141 u_long
1142 GetMask(addr)
1143     u_long addr;
1144 {
1145     return(netmask);
1146 }
1147
1148 /*
1149  * dumpbuffer - print contents of a buffer in hex to standard output.
1150  */
1151 void
1152 dumpbuffer(buffer, size, level)
1153     unsigned char *buffer;
1154     int size;
1155     int level;
1156 {
1157     register int i;
1158     char line[256], *p;
1159
1160     printf("%d bytes:\n", size);
1161     while (size > 0)
1162     {
1163         p = line;
1164         sprintf(p, "%08lx: ", buffer);
1165         p += 10;
1166                 
1167         for (i = 0; i < 8; i++, p += 3)
1168             if (size - i <= 0)
1169                 sprintf(p, "xx ");
1170             else
1171                 sprintf(p, "%02x ", buffer[i]);
1172
1173         for (i = 0; i < 8; i++)
1174             if (size - i <= 0)
1175                 *p++ = 'x';
1176             else
1177                 *p++ = (' ' <= buffer[i] && buffer[i] <= '~') ?
1178                     buffer[i] : '.';
1179
1180         *p++ = 0;
1181         buffer += 8;
1182         size -= 8;
1183
1184 /*      syslog(level, "%s\n", line); */
1185         printf("%s\n", line);
1186         fflush(stdout);
1187     }
1188 }
1189
1190
1191 /*
1192  * setdtr - control the DTR line on the serial port.
1193  * This is called from die(), so it shouldn't call die().
1194  */
1195 setdtr(fd, on)
1196 int fd, on;
1197 {
1198     int modembits = TIOCM_DTR;
1199
1200     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
1201 }
1202
1203 #include <varargs.h>
1204
1205 char line[256];
1206 char *p;
1207
1208 logf(level, fmt, va_alist)
1209 int level;
1210 char *fmt;
1211 va_dcl
1212 {
1213     va_list pvar;
1214     char buf[256];
1215
1216     va_start(pvar);
1217     vsprintf(buf, fmt, pvar);
1218     va_end(pvar);
1219
1220     p = line + strlen(line);
1221     strcat(p, buf);
1222
1223     if (buf[strlen(buf)-1] == '\n') {
1224         syslog(level, "%s", line);
1225         line[0] = 0;
1226     }
1227 }
1228
1229 void
1230 novm(msg)
1231     char *msg;
1232 {
1233     syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
1234     die(1);
1235 }