fix stats stuff
[ppp.git] / pppd / sys-linux.c
1 /*
2  * sys-linux.c - System-dependent procedures for setting up
3  * PPP interfaces on Linux systems
4  *
5  * Copyright (c) 1989 Carnegie Mellon University.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by Carnegie Mellon University.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20
21 /*
22  * TODO:
23  */
24
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/time.h>
29 #include <sys/errno.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <syslog.h>
34 #include <string.h>
35 #include <time.h>
36 #include <memory.h>
37 #include <utmp.h>
38 #include <mntent.h>
39 #include <signal.h>
40 #include <fcntl.h>
41
42 #include <net/if.h>
43 #include <net/ppp_defs.h>
44 #include <net/if_arp.h>
45 #include <linux/if_ppp.h>
46 #include <net/if_route.h>
47 #include <linux/if_ether.h>
48 #include <netinet/in.h>
49
50 #include "pppd.h"
51 #include "fsm.h"
52 #include "ipcp.h"
53
54 static int initdisc = -1;       /* Initial TTY discipline */
55 static int prev_kdebugflag = 0;
56
57 static int restore_term;                /* 1 => we've munged the terminal */
58 static struct termios inittermios;      /* Initial TTY termios */
59
60 int sockfd;                     /* socket for doing interface ioctls */
61
62 static int driver_version = 0;
63 static int driver_modification = 0;
64 static int driver_patch = 0;
65
66 static char *lock_file;
67
68 #define MAX_IFS         32
69
70 /*
71  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
72  * if it exists.
73  */
74
75 #define SET_SA_FAMILY(addr, family)                     \
76     memset ((char *) &(addr), '\0', sizeof(addr));      \
77     addr.sa_family = (family);
78
79 /*
80  * sys_init - System-dependent initialization.
81  */
82
83 void sys_init(void)
84 {
85     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
86     setlogmask(LOG_UPTO(LOG_INFO));
87     if (debug)
88         setlogmask(LOG_UPTO(LOG_DEBUG));
89
90     /* Get an internet socket for doing socket ioctl's on. */
91     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
92         syslog(LOG_ERR, "Couldn't create IP socket: %m");
93         die(1);
94     }
95 }
96
97 /*
98  * note_debug_level - note a change in the debug level.
99  */
100 void note_debug_level (void)
101 {
102     if (debug) {
103         syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
104         setlogmask(LOG_UPTO(LOG_DEBUG));
105     } else {
106         setlogmask(LOG_UPTO(LOG_WARNING));
107     }
108 }
109
110 /*
111  * set_kdebugflag - Define the debugging level for the kernel
112  */
113
114 int set_kdebugflag (int requested_level)
115 {
116     if (ioctl(fd, PPPIOCGDEBUG, &prev_kdebugflag) < 0) {
117         syslog(LOG_ERR, "ioctl(PPPIOCGDEBUG): %m");
118         return (0);
119     }
120
121     if (prev_kdebugflag != requested_level) {
122         if (ioctl(fd, PPPIOCSDEBUG, &requested_level) < 0) {
123             syslog (LOG_ERR, "ioctl(PPPIOCSDEBUG): %m");
124             return (0);
125         }
126         syslog(LOG_INFO, "set kernel debugging level to %d", requested_level);
127     }
128     return (1);
129 }
130
131 /*
132  * establish_ppp - Turn the serial port into a ppp interface.
133  */
134
135 void establish_ppp (void)
136 {
137     int pppdisc = N_PPP;
138     int sig     = SIGIO;
139
140     if (ioctl(fd, TIOCEXCL, 0) < 0) {
141         syslog (LOG_WARNING, "ioctl(TIOCEXCL): %m");
142     }
143
144     if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
145         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
146         die (1);
147     }
148     
149     if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
150         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
151         die (1);
152     }
153     if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {
154         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
155         die (1);
156     }
157
158     set_kdebugflag (kdebugflag);
159
160     syslog (LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
161             driver_version, driver_modification, driver_patch);
162 }
163
164 /*
165  * disestablish_ppp - Restore the serial port to normal operation.
166  * This shouldn't call die() because it's called from die().
167  */
168
169 void disestablish_ppp(void)
170 {
171     int x;
172     char *s;
173
174     if (initdisc >= 0) {
175         set_kdebugflag (prev_kdebugflag);
176         /*
177          * Check whether the link seems not to be 8-bit clean.
178          */
179         if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
180             s = NULL;
181             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
182             case SC_RCV_B7_0:
183                 s = "bit 7 set to 1";
184                 break;
185             case SC_RCV_B7_1:
186                 s = "bit 7 set to 0";
187                 break;
188             case SC_RCV_EVNP:
189                 s = "odd parity";
190                 break;
191             case SC_RCV_ODDP:
192                 s = "even parity";
193                 break;
194             }
195             if (s != NULL) {
196                 syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
197                 syslog(LOG_WARNING, "All received characters had %s", s);
198             }
199         }
200
201         if (ioctl(fd, TIOCSETD, &initdisc) < 0)
202             syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
203
204         if (ioctl(fd, TIOCNXCL, 0) < 0)
205             syslog (LOG_WARNING, "ioctl(TIOCNXCL): %m");
206
207         initdisc = -1;
208     }
209 }
210
211 /*
212  * List of valid speeds.
213  */
214 struct speed {
215     int speed_int, speed_val;
216 } speeds[] = {
217 #ifdef B50
218     { 50, B50 },
219 #endif
220 #ifdef B75
221     { 75, B75 },
222 #endif
223 #ifdef B110
224     { 110, B110 },
225 #endif
226 #ifdef B134
227     { 134, B134 },
228 #endif
229 #ifdef B150
230     { 150, B150 },
231 #endif
232 #ifdef B200
233     { 200, B200 },
234 #endif
235 #ifdef B300
236     { 300, B300 },
237 #endif
238 #ifdef B600
239     { 600, B600 },
240 #endif
241 #ifdef B1200
242     { 1200, B1200 },
243 #endif
244 #ifdef B1800
245     { 1800, B1800 },
246 #endif
247 #ifdef B2000
248     { 2000, B2000 },
249 #endif
250 #ifdef B2400
251     { 2400, B2400 },
252 #endif
253 #ifdef B3600
254     { 3600, B3600 },
255 #endif
256 #ifdef B4800
257     { 4800, B4800 },
258 #endif
259 #ifdef B7200
260     { 7200, B7200 },
261 #endif
262 #ifdef B9600
263     { 9600, B9600 },
264 #endif
265 #ifdef B19200
266     { 19200, B19200 },
267 #endif
268 #ifdef B38400
269     { 38400, B38400 },
270 #endif
271 #ifdef EXTA
272     { 19200, EXTA },
273 #endif
274 #ifdef EXTB
275     { 38400, EXTB },
276 #endif
277 #ifdef B57600
278     { 57600, B57600 },
279 #endif
280 #ifdef B115200
281     { 115200, B115200 },
282 #endif
283     { 0, 0 }
284 };
285
286 /*
287  * Translate from bits/second to a speed_t.
288  */
289 int translate_speed (int bps)
290 {
291     struct speed *speedp;
292
293     if (bps == 0)
294         return 0;
295     for (speedp = speeds; speedp->speed_int; speedp++)
296         if (bps == speedp->speed_int)
297             return speedp->speed_val;
298     syslog(LOG_WARNING, "speed %d not supported", bps);
299     return 0;
300 }
301
302 /*
303  * Translate from a speed_t to bits/second.
304  */
305 int baud_rate_of (int speed)
306 {
307     struct speed *speedp;
308
309     if (speed == 0)
310         return 0;
311     for (speedp = speeds; speedp->speed_int; speedp++)
312         if (speed == speedp->speed_val)
313             return speedp->speed_int;
314     return 0;
315 }
316
317 /*
318  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
319  * at the requested speed, etc.  If `local' is true, set CLOCAL
320  * regardless of whether the modem option was specified.
321  */
322 void set_up_tty (int fd, int local)
323 {
324     int speed, x;
325     struct termios tios;
326
327     if (tcgetattr(fd, &tios) < 0) {
328         syslog(LOG_ERR, "tcgetattr: %m");
329         die(1);
330     }
331
332     if (!restore_term)
333         inittermios = tios;
334
335     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
336     if (crtscts == 1)
337         tios.c_cflag |= CRTSCTS;
338     else if (crtscts < 0)
339         tios.c_cflag &= ~CRTSCTS;
340
341     tios.c_cflag |= CS8 | CREAD | HUPCL;
342
343     if (local || !modem)
344         tios.c_cflag |= CLOCAL;
345
346     tios.c_iflag      = IGNBRK | IGNPAR;
347     tios.c_oflag      = 0;
348     tios.c_lflag      = 0;
349     tios.c_cc[VMIN]   = 1;
350     tios.c_cc[VTIME]  = 0;
351
352     if (crtscts == 2) {
353         tios.c_iflag     |= IXOFF;
354         tios.c_cc[VSTOP]  = 0x13;       /* DC3 = XOFF = ^S */
355         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
356     }
357
358     speed = translate_speed(inspeed);
359     if (speed) {
360         cfsetospeed(&tios, speed);
361         cfsetispeed(&tios, speed);
362     } else {
363         speed = cfgetospeed(&tios);
364         /*
365          * We can't proceed if the serial port speed is B0,
366          * since that implies that the serial port is disabled.
367          */
368         if (speed == B0) {
369             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
370                    devnam);
371             die(1);
372         }
373     }
374
375     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
376         syslog(LOG_ERR, "tcsetattr: %m");
377         die(1);
378     }
379
380     baud_rate = baud_rate_of(speed);
381     restore_term = TRUE;
382 }
383
384 /*
385  * setdtr - control the DTR line on the serial port.
386  * This is called from die(), so it shouldn't call die().
387  */
388 void setdtr (int fd, int on)
389 {
390     int modembits = TIOCM_DTR;
391
392     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
393 }
394
395 /*
396  * restore_tty - restore the terminal to the saved settings.
397  */
398
399 void restore_tty (void)
400 {
401     if (restore_term) {
402         if (!default_device) {
403             /*
404              * Turn off echoing, because otherwise we can get into
405              * a loop with the tty and the modem echoing to each other.
406              * We presume we are the sole user of this tty device, so
407              * when we close it, it will revert to its defaults anyway.
408              */
409             inittermios.c_lflag &= ~(ECHO | ECHONL);
410         }
411         if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
412             if (errno != ENXIO)
413                 syslog(LOG_WARNING, "tcsetattr: %m");
414         restore_term = 0;
415     }
416 }
417
418 /*
419  * output - Output PPP packet.
420  */
421
422 void output (int unit, unsigned char *p, int len)
423 {
424     if (unit != 0)
425         MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
426
427     if (debug)
428         log_packet(p, len, "sent ");
429     
430     if (write(fd, p, len) < 0) {
431         syslog(LOG_ERR, "write: %m");
432         die(1);
433     }
434 }
435
436 /*
437  * wait_input - wait until there is data available on fd,
438  * for the length of time specified by *timo (indefinite
439  * if timo is NULL).
440  */
441 void wait_input (struct timeval *timo)
442 {
443     fd_set ready;
444     int n;
445
446     FD_ZERO(&ready);
447     FD_SET(fd, &ready);
448     n = select(fd+1, &ready, NULL, &ready, timo);
449     if (n < 0 && errno != EINTR) {
450         syslog(LOG_ERR, "select: %m");
451         die(1);
452     }
453 }
454
455 /*
456  * read_packet - get a PPP packet from the serial device.
457  */
458
459 int read_packet (unsigned char *buf)
460 {
461     int len;
462   
463     len = read(fd, buf, PPP_MTU + PPP_HDRLEN);
464     if (len < 0) {
465         if (errno == EWOULDBLOCK) {
466             return -1;
467         }
468         syslog(LOG_ERR, "read(fd): %m");
469         die(1);
470     }
471     return len;
472 }
473
474 /*
475  * ppp_send_config - configure the transmit characteristics of
476  * the ppp interface.
477  */
478 void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
479 {
480     u_int x;
481     struct ifreq ifr;
482   
483     MAINDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
484     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
485     ifr.ifr_mtu = mtu;
486     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
487         syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
488         quit();
489     }
490
491     MAINDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
492     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
493         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
494         quit();
495     }
496     
497     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
498         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
499         quit();
500     }
501
502     x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
503     x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
504
505     MAINDEBUG ((LOG_DEBUG, "send_config: flags = %x\n", x));
506     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
507         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
508         quit();
509     }
510 }
511
512 /*
513  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
514  */
515 void ppp_set_xaccm (int unit, ext_accm accm)
516 {
517     MAINDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
518                 accm[0], accm[1], accm[2], accm[3]));
519     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
520         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
521 }
522
523 /*
524  * ppp_recv_config - configure the receive-side characteristics of
525  * the ppp interface.
526  */
527 void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
528 {
529     u_int x;
530
531     MAINDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
532     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
533         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
534
535     MAINDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
536     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
537         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
538         quit();
539     }
540   
541     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
542         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
543         quit();
544     }
545
546     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
547     MAINDEBUG ((LOG_DEBUG, "recv_config: flags = %x\n", x));
548     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
549         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
550         quit();
551     }
552 }
553
554 /*
555  * ccp_test - ask kernel whether a given compression method
556  * is acceptable for use.
557  */
558 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
559   {
560     struct ppp_option_data data;
561
562     data.ptr      = opt_ptr;
563     data.length   = opt_len;
564     data.transmit = for_transmit;
565
566     return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
567   }
568
569 /*
570  * ccp_flags_set - inform kernel about the current state of CCP.
571  */
572
573 void ccp_flags_set (int unit, int isopen, int isup)
574   {
575     int x;
576
577     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
578       {
579         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
580       }
581     else
582       {
583         x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
584         x = isup?   x | SC_CCP_UP   : x &~ SC_CCP_UP;
585
586         if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
587           {
588             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
589           }
590       }
591   }
592
593 /*
594  * ccp_fatal_error - returns 1 if decompression was disabled as a
595  * result of an error detected after decompression of a packet,
596  * 0 otherwise.  This is necessary because of patent nonsense.
597  */
598
599 int ccp_fatal_error (int unit)
600   {
601     int x;
602
603     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
604       {
605         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
606         return 0;
607       }
608     return x & SC_DC_FERROR;
609   }
610
611 /*
612  * sifvjcomp - config tcp header compression
613  */
614
615 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
616   {
617     u_int x;
618
619     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
620       {
621         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
622         return 0;
623       }
624
625     x = vjcomp  ? x | SC_COMP_TCP     : x &~ SC_COMP_TCP;
626     x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
627
628     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
629       {
630         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
631         return 0;
632       }
633
634     if (vjcomp)
635       {
636         if (ioctl (fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
637           {
638             syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
639             return 0;
640           }
641       }
642
643     return 1;
644   }
645
646 /*
647  * sifup - Config the interface up and enable IP packets to pass.
648  */
649
650 int sifup (int u)
651   {
652     struct ifreq ifr;
653
654     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
655     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
656       {
657         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
658         return 0;
659       }
660
661     ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
662     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
663       {
664         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
665         return 0;
666       }
667     return 1;
668   }
669
670 /*
671  * sifdown - Config the interface down and disable IP.
672  */
673
674 int sifdown (int u)
675   {
676     struct ifreq ifr;
677
678     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
679     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
680       {
681         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
682         return 0;
683       }
684
685     ifr.ifr_flags &= ~IFF_UP;
686     ifr.ifr_flags |= IFF_POINTOPOINT;
687     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
688       {
689         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
690         return 0;
691       }
692     return 1;
693   }
694
695 /*
696  * sifaddr - Config the interface IP addresses and netmask.
697  */
698
699 int sifaddr (int unit, int our_adr, int his_adr, int net_mask)
700   {
701     struct ifreq   ifr; 
702     struct rtentry rt;
703     
704     SET_SA_FAMILY (ifr.ifr_addr,    AF_INET); 
705     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); 
706     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); 
707
708     strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
709 /*
710  *  Set our IP address
711  */
712     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
713     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
714       {
715         if (errno != EEXIST)
716           {
717             syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m");
718           }
719         else
720           {
721             syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
722           }
723         return (0);
724       } 
725 /*
726  *  Set the gateway address
727  */
728     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
729     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
730       {
731         syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m"); 
732         return (0);
733       } 
734 /*
735  *  Set the netmask
736  */
737     if (net_mask != 0)
738       {
739         ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
740         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
741           {
742             syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m"); 
743             return (0);
744           } 
745       }
746 /*
747  *  Add the device route
748  */
749     memset (&rt, '\0', sizeof (rt));
750
751     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
752     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
753     rt.rt_dev = ifname;  /* MJC */
754
755     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
756     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
757     rt.rt_flags = RTF_UP | RTF_HOST;
758
759     if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
760       {
761         syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m");
762         return (0);
763       }
764     return 1;
765   }
766
767 /*
768  * cifaddr - Clear the interface IP addresses, and delete routes
769  * through the interface if possible.
770  */
771
772 int cifaddr (int unit, int our_adr, int his_adr)
773   {
774     struct rtentry rt;
775 /*
776  *  Delete the route through the device
777  */
778     memset (&rt, '\0', sizeof (rt));
779
780     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
781     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
782     rt.rt_dev = ifname;  /* MJC */
783
784     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
785     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
786     rt.rt_flags = RTF_UP | RTF_HOST;
787
788     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
789       {
790         syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m");
791         return (0);
792       }
793     return 1;
794   }
795
796 /*
797  * path_to_route - determine the path to the proc file system data
798  */
799
800 FILE *route_fd = (FILE *) 0;
801 static char route_buffer [100];
802
803 static char *path_to_route (void);
804 static int open_route_table (void);
805 static void close_route_table (void);
806 static int read_route_table (struct rtentry *rt);
807 static int defaultroute_exists (void);
808
809 /*
810  * path_to_route - find the path to the route tables in the proc file system
811  */
812
813 static char *path_to_route (void)
814   {
815     struct mntent *mntent;
816     FILE *fp;
817
818     fp = fopen (MOUNTED, "r");
819     if (fp != 0)
820       {
821         while ((mntent = getmntent (fp)) != 0)
822           {
823             if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) == 0)
824               {
825                 continue;
826               }
827
828             if (strcmp (mntent->mnt_type, "proc") == 0)
829               {
830                 strncpy (route_buffer, mntent->mnt_dir,
831                          sizeof (route_buffer)-10);
832                 route_buffer [sizeof (route_buffer)-10] = '\0';
833                 strcat (route_buffer, "/net/route");
834
835                 fclose (fp);
836                 return (route_buffer);
837               }
838           }
839         fclose (fp);
840       }
841     syslog (LOG_ERR, "proc file system not mounted");
842     return 0;
843   }
844
845 /*
846  * open_route_table - open the interface to the route table
847  */
848
849 static int open_route_table (void)
850   {
851     char *path;
852
853     if (route_fd != (FILE *) 0)
854       {
855         close_route_table();
856       }
857
858     path = path_to_route();
859     if (path == NULL)
860       {
861         return 0;
862       }
863
864     route_fd = fopen (path, "r");
865     if (route_fd == (FILE *) 0)
866       {
867         syslog (LOG_ERR, "can not open %s: %m", path);
868         return 0;
869       }
870
871     /* read and discard the header line. */
872     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
873       {
874         close_route_table();
875         return 0;
876       }
877     return 1;
878   }
879
880 /*
881  * close_route_table - close the interface to the route table
882  */
883
884 static void close_route_table (void)
885   {
886     if (route_fd != (FILE *) 0)
887       {
888         fclose (route_fd);
889         route_fd = (FILE *) 0;
890       }
891   }
892
893 /*
894  * read_route_table - read the next entry from the route table
895  */
896
897 static int read_route_table (struct rtentry *rt)
898   {
899     static char delims[] = " \t\n";
900     char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
901
902     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
903       {
904         return 0;
905       }
906
907     memset (rt, '\0', sizeof (struct rtentry));
908
909     dev_ptr  = strtok (route_buffer, delims); /* interface name */
910     dst_ptr  = strtok (NULL,         delims); /* destination address */
911     gw_ptr   = strtok (NULL,         delims); /* gateway */
912     flag_ptr = strtok (NULL,         delims); /* flags */
913
914     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
915       strtoul (dst_ptr, NULL, 16);
916
917     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
918       strtoul (gw_ptr, NULL, 16);
919
920     rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
921     rt->rt_dev   = dev_ptr;
922
923     return 1;
924   }
925
926 /*
927  * defaultroute_exists - determine if there is a default route
928  */
929
930 static int defaultroute_exists (void)
931   {
932     struct rtentry rt;
933     int    result = 0;
934
935     if (!open_route_table())
936       {
937         return 0;
938       }
939
940     while (read_route_table(&rt) != 0)
941       {
942         if (rt.rt_flags & RTF_UP == 0)
943           {
944             continue;
945           }
946
947         if (((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr == 0L)
948           {
949             syslog (LOG_ERR,
950                     "ppp not replacing existing default route to %s[%s]",
951                     rt.rt_dev,
952                     inet_ntoa (((struct sockaddr_in *) &rt.rt_gateway)->
953                                sin_addr.s_addr));
954             result = 1;
955             break;
956           }
957       }
958     close_route_table();
959     return result;
960   }
961
962 /*
963  * sifdefaultroute - assign a default route through the address given.
964  */
965
966 int sifdefaultroute (int unit, int gateway)
967   {
968     struct rtentry rt;
969
970     if (defaultroute_exists())
971       {
972         return 0;
973       }
974
975     memset (&rt, '\0', sizeof (rt));
976     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
977     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
978     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
979     
980     rt.rt_flags = RTF_UP | RTF_GATEWAY;
981     if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
982       {
983         syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m");
984         return 0;
985       }
986     return 1;
987   }
988
989 /*
990  * cifdefaultroute - delete a default route through the address given.
991  */
992
993 int cifdefaultroute (int unit, int gateway)
994   {
995     struct rtentry rt;
996   
997     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
998     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
999     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1000     
1001     rt.rt_flags = RTF_UP | RTF_GATEWAY;
1002     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
1003       {
1004         syslog (LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1005         return 0;
1006       }
1007     return 1;
1008   }
1009
1010 /*
1011  * sifproxyarp - Make a proxy ARP entry for the peer.
1012  */
1013
1014 int sifproxyarp (int unit, u_int32_t his_adr)
1015   {
1016     struct arpreq arpreq;
1017
1018     memset (&arpreq, '\0', sizeof(arpreq));
1019 /*
1020  * Get the hardware address of an interface on the same subnet
1021  * as our local address.
1022  */
1023     if (!get_ether_addr(his_adr, &arpreq.arp_ha))
1024       {
1025         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1026         return 0;
1027       }
1028     
1029     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1030     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1031     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1032     
1033     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0)
1034       {
1035         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1036         return 0;
1037       }
1038     return 1;
1039   }
1040
1041 /*
1042  * cifproxyarp - Delete the proxy ARP entry for the peer.
1043  */
1044
1045 int cifproxyarp (int unit, u_int32_t his_adr)
1046   {
1047     struct arpreq arpreq;
1048   
1049     memset (&arpreq, '\0', sizeof(arpreq));
1050     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1051     
1052     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1053     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0)
1054       {
1055         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1056         return 0;
1057       }
1058     return 1;
1059   }
1060      
1061 /*
1062  * get_ether_addr - get the hardware address of an interface on the
1063  * the same subnet as ipaddr.
1064  */
1065
1066 int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr)
1067   {
1068     struct ifreq *ifr, *ifend, *ifp;
1069     int i;
1070     u_int32_t ina, mask;
1071     struct sockaddr_dl *dla;
1072     struct ifreq ifreq;
1073     struct ifconf ifc;
1074     struct ifreq ifs[MAX_IFS];
1075     
1076     ifc.ifc_len = sizeof(ifs);
1077     ifc.ifc_req = ifs;
1078     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1079       {
1080         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1081         return 0;
1082       }
1083     MAINDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
1084                 ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
1085 /*
1086  * Scan through looking for an interface with an Internet
1087  * address on the same subnet as `ipaddr'.
1088  */
1089     ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1090     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1091       {
1092         if (ifr->ifr_addr.sa_family == AF_INET)
1093           {
1094             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1095             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1096             MAINDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
1097                         ifreq.ifr_name));
1098 /*
1099  * Check that the interface is up, and not point-to-point
1100  * or loopback.
1101  */
1102             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1103               {
1104                 continue;
1105               }
1106             if ((ifreq.ifr_flags &
1107                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1108                 != (IFF_UP|IFF_BROADCAST))
1109               {
1110                 continue;
1111               }
1112 /*
1113  * Get its netmask and check that it's on the right subnet.
1114  */
1115             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1116               {
1117                 continue;
1118               }
1119             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1120             MAINDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
1121                         ip_ntoa(ina), ntohl(mask)));
1122             if (((ipaddr ^ ina) & mask) != 0)
1123               {
1124                 continue;
1125               }
1126             break;
1127           }
1128       }
1129     
1130     if (ifr >= ifend)
1131       {
1132         return 0;
1133       }
1134
1135     syslog(LOG_INFO, "found interface %s for proxy arp", ifreq.ifr_name);
1136 /*
1137  * Now get the hardware address.
1138  */
1139     if (ioctl (sockfd, SIOCGIFHWADDR, &ifreq) < 0)
1140       {
1141         syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m", ifreq.ifr_name);
1142         return 0;
1143       }
1144
1145     hwaddr->sa_family = ARPHRD_ETHER;
1146     memcpy (&hwaddr->sa_data, &ifreq.ifr_hwaddr.sa_data, ETH_ALEN);
1147
1148     MAINDEBUG ((LOG_DEBUG,
1149                 "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x",
1150                 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1151                 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1152                 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1153                 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1154                 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1155                 (int) ((unsigned char *) &hwaddr->sa_data)[5]));
1156     return 1;
1157   }
1158
1159 /*
1160  * Return user specified netmask, modified by any mask we might determine
1161  * for address `addr' (in network byte order).
1162  * Here we scan through the system's list of interfaces, looking for
1163  * any non-point-to-point interfaces which might appear to be on the same
1164  * network as `addr'.  If we find any, we OR in their netmask to the
1165  * user-specified netmask.
1166  */
1167 u_int32_t
1168 GetMask(addr)
1169     u_int32_t addr;
1170 {
1171     u_int32_t mask, nmask, ina;
1172     struct ifreq *ifr, *ifend, ifreq;
1173     struct ifconf ifc;
1174     struct ifreq ifs[MAX_IFS];
1175
1176     addr = ntohl(addr);
1177     if (IN_CLASSA(addr))        /* determine network mask for address class */
1178         nmask = IN_CLASSA_NET;
1179     else if (IN_CLASSB(addr))
1180         nmask = IN_CLASSB_NET;
1181     else
1182         nmask = IN_CLASSC_NET;
1183     /* class D nets are disallowed by bad_ip_adrs */
1184     mask = netmask | htonl(nmask);
1185
1186     /*
1187      * Scan through the system's network interfaces.
1188      */
1189     ifc.ifc_len = sizeof(ifs);
1190     ifc.ifc_req = ifs;
1191     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1192         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1193         return mask;
1194     }
1195     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1196     for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
1197         /*
1198          * Check the interface's internet address.
1199          */
1200         if (ifr->ifr_addr.sa_family != AF_INET)
1201             continue;
1202         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1203         if ((ntohl(ina) & nmask) != (addr & nmask))
1204             continue;
1205         /*
1206          * Check that the interface is up, and not point-to-point or loopback.
1207          */
1208         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1209         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1210             continue;
1211         if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1212             != IFF_UP)
1213             continue;
1214         /*
1215          * Get its netmask and OR it into our mask.
1216          */
1217         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1218             continue;
1219         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1220     }
1221
1222     return mask;
1223 }
1224
1225 /*
1226  * Internal routine to decode the version.modification.patch level
1227  */
1228
1229 static void decode_version (char *buf, int *version,
1230                             int *modification, int *patch)
1231   {
1232
1233     *version      = (int) strtoul (buf, &buf, 10);
1234     *modification = 0;
1235     *patch        = 0;
1236     
1237     if (*buf == '.')
1238       {
1239         ++buf;
1240         *modification = (int) strtoul (buf, &buf, 10);
1241         if (*buf == '.')
1242           {
1243             ++buf;
1244             *patch = (int) strtoul (buf, &buf, 10);
1245           }
1246       }
1247     
1248     if (*buf != '\0')
1249       {
1250         *version      =
1251         *modification =
1252         *patch        = 0;
1253       }
1254   }
1255
1256 /*
1257  * ppp_available - check whether the system has any ppp interfaces
1258  * (in fact we check whether we can do an ioctl on ppp0).
1259  */
1260
1261 int ppp_available(void)
1262   {
1263     int s, ok;
1264     struct ifreq ifr;
1265     int my_version,     my_modification,     my_patch;
1266 /*
1267  * Open a socket for doing the ioctl operations.
1268  */    
1269     s = socket(AF_INET, SOCK_DGRAM, 0);
1270     if (s < 0)
1271       {
1272         return 0;
1273       }
1274     
1275     strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1276     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1277 /*
1278  * Ensure that the hardware address is for PPP and not something else
1279  */
1280     if (ok != 0)
1281       {
1282         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
1283       }
1284
1285     if (ok != 0 && ifr.ifr_hwaddr.sa_family != ARPHRD_PPP)
1286       {
1287         ok = 0;
1288       }
1289 /*
1290  *  This is the PPP device. Validate the version of the driver at this
1291  *  point to ensure that this program will work with the driver.
1292  */
1293     if (ok != 0)
1294       {
1295         char   abBuffer [1024];
1296         int    size;
1297
1298         ifr.ifr_data = abBuffer;
1299         size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
1300         ok   = size >= 0;
1301
1302         if (ok != 0)
1303           {
1304             decode_version (abBuffer,
1305                             &driver_version,
1306                             &driver_modification,
1307                             &driver_patch);
1308           }
1309       }
1310     
1311     if (ok == 0)
1312       {
1313         driver_version      =
1314         driver_modification =
1315         driver_patch        = 0;
1316       }
1317 /*
1318  * Validate the version of the driver against the version that we used.
1319  */
1320     decode_version (PPP_VERSION,
1321                     &my_version,
1322                     &my_modification,
1323                     &my_patch);
1324
1325     /* The version numbers must match */
1326     if (driver_version != my_version)
1327       {
1328         ok = 0;
1329       }
1330       
1331     /* The modification levels must be legal */
1332     if (driver_modification < my_modification)
1333       {
1334         ok = 0;
1335       }
1336
1337     if (ok == 0)
1338       {
1339         fprintf(stderr, "Sorry - PPP driver version %d.%d.%d is out of date\n",
1340                 driver_version, driver_modification, driver_patch);
1341       }
1342     
1343     close(s);
1344     return ok;
1345   }
1346
1347 int logwtmp (char *line, char *name, char *host)
1348   {
1349     struct utmp ut;
1350     int    mode;
1351 /*
1352  * Control the 'mesg' function based upon the state of the logon
1353  * operation.
1354  */
1355     mode = (*name != '\0') ? 0600 : 0622;
1356     if (chmod (devnam, mode) < 0)
1357       {
1358         syslog (LOG_ERR, "chmod(\"%s\", 0%o): %m", devnam, mode);
1359       }
1360 /*
1361  * Update the signon database for users.
1362  */
1363     memset (&ut, 0, sizeof (ut));
1364     (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1365     (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1366     (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1367     (void)time(&ut.ut_time);
1368         
1369     pututline (&ut);            /* Write the line to the proper place */
1370     endutent();                 /* Indicate operation is complete */
1371   }
1372
1373 /*
1374  * Code for locking/unlocking the serial device.
1375  * This code is derived from chat.c.
1376  */
1377
1378 #define LOCK_PREFIX     "/var/lock/LCK.."
1379
1380 /*
1381  * lock - create a lock file for the named device
1382  */
1383 int
1384 lock(dev)
1385     char *dev;
1386 {
1387     char hdb_lock_buffer[12];
1388     int fd, pid, n;
1389     char *p;
1390
1391     if ((p = strrchr(dev, '/')) != NULL)
1392         dev = p + 1;
1393     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1394     if (lock_file == NULL)
1395         novm("lock file name");
1396     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1397
1398     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1399         if (errno == EEXIST
1400             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1401             /* Read the lock file to find out who has the device locked */
1402             n = read(fd, hdb_lock_buffer, 11);
1403             if (n > 0) {
1404                 hdb_lock_buffer[n] = 0;
1405                 sscanf (hdb_lock_buffer, " %d", &pid);
1406             }
1407             if (n <= 0) {
1408                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1409                 close(fd);
1410             } else {
1411                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1412                     /* pid no longer exists - remove the lock file */
1413                     if (unlink(lock_file) == 0) {
1414                         close(fd);
1415                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1416                                dev, pid);
1417                         continue;
1418                     } else
1419                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1420                                dev);
1421                 } else
1422                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1423                            dev, pid);
1424             }
1425             close(fd);
1426         } else
1427             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1428         free(lock_file);
1429         lock_file = NULL;
1430         return -1;
1431     }
1432
1433     sprintf(hdb_lock_buffer, "%010d\n", getpid());
1434     write(fd, hdb_lock_buffer, 11);
1435
1436     close(fd);
1437     return 0;
1438 }
1439
1440 /*
1441  * unlock - remove our lockfile
1442  */
1443 unlock()
1444 {
1445     if (lock_file) {
1446         unlink(lock_file);
1447         free(lock_file);
1448         lock_file = NULL;
1449     }
1450 }