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