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