]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-linux.c
removed GetMask (gone to sys-*.c)
[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 <net/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 (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
403             if (errno != ENXIO)
404                 syslog(LOG_WARNING, "tcsetattr: %m");
405         restore_term = 0;
406     }
407 }
408
409 /*
410  * output - Output PPP packet.
411  */
412
413 void output (int unit, unsigned char *p, int len)
414 {
415     if (unit != 0)
416         MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
417
418     if (debug)
419         log_packet(p, len, "sent ");
420     
421     if (write(fd, p, len) < 0) {
422         syslog(LOG_ERR, "write: %m");
423         die(1);
424     }
425 }
426
427 /*
428  * wait_input - wait until there is data available on fd,
429  * for the length of time specified by *timo (indefinite
430  * if timo is NULL).
431  */
432 void wait_input (struct timeval *timo)
433 {
434     fd_set ready;
435     int n;
436
437     FD_ZERO(&ready);
438     FD_SET(fd, &ready);
439     n = select(fd+1, &ready, NULL, &ready, timo);
440     if (n < 0 && errno != EINTR) {
441         syslog(LOG_ERR, "select: %m");
442         die(1);
443     }
444 }
445
446 /*
447  * read_packet - get a PPP packet from the serial device.
448  */
449
450 int read_packet (unsigned char *buf)
451 {
452     int len;
453   
454     len = read(fd, buf, PPP_MTU + PPP_HDRLEN);
455     if (len < 0) {
456         if (errno == EWOULDBLOCK) {
457             return -1;
458         }
459         syslog(LOG_ERR, "read(fd): %m");
460         die(1);
461     }
462     return len;
463 }
464
465 /*
466  * ppp_send_config - configure the transmit characteristics of
467  * the ppp interface.
468  */
469 void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
470 {
471     u_int x;
472     struct ifreq ifr;
473   
474     MAINDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
475     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
476     ifr.ifr_mtu = mtu;
477     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
478         syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
479         quit();
480     }
481
482     MAINDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
483     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
484         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
485         quit();
486     }
487     
488     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
489         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
490         quit();
491     }
492
493     x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
494     x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
495
496     MAINDEBUG ((LOG_DEBUG, "send_config: flags = %x\n", x));
497     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
498         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
499         quit();
500     }
501 }
502
503 /*
504  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
505  */
506 void ppp_set_xaccm (int unit, ext_accm accm)
507 {
508     MAINDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
509                 accm[0], accm[1], accm[2], accm[3]));
510     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
511         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
512 }
513
514 /*
515  * ppp_recv_config - configure the receive-side characteristics of
516  * the ppp interface.
517  */
518 void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
519 {
520     u_int x;
521
522     MAINDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
523     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
524         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
525
526     MAINDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
527     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
528         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
529         quit();
530     }
531   
532     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
533         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
534         quit();
535     }
536
537     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
538     MAINDEBUG ((LOG_DEBUG, "recv_config: flags = %x\n", x));
539     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
540         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
541         quit();
542     }
543 }
544
545 /*
546  * ccp_test - ask kernel whether a given compression method
547  * is acceptable for use.
548  */
549 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
550   {
551     struct ppp_option_data data;
552
553     data.ptr      = opt_ptr;
554     data.length   = opt_len;
555     data.transmit = for_transmit;
556
557     return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
558   }
559
560 /*
561  * ccp_flags_set - inform kernel about the current state of CCP.
562  */
563
564 void ccp_flags_set (int unit, int isopen, int isup)
565   {
566     int x;
567
568     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
569       {
570         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
571       }
572     else
573       {
574         x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
575         x = isup?   x | SC_CCP_UP   : x &~ SC_CCP_UP;
576
577         if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
578           {
579             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
580           }
581       }
582   }
583
584 /*
585  * ccp_fatal_error - returns 1 if decompression was disabled as a
586  * result of an error detected after decompression of a packet,
587  * 0 otherwise.  This is necessary because of patent nonsense.
588  */
589
590 int ccp_fatal_error (int unit)
591   {
592     int x;
593
594     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
595       {
596         syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
597         return 0;
598       }
599     return x & SC_DC_FERROR;
600   }
601
602 /*
603  * sifvjcomp - config tcp header compression
604  */
605
606 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
607   {
608     u_int x;
609
610     if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
611       {
612         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
613         return 0;
614       }
615
616     x = vjcomp  ? x | SC_COMP_TCP     : x &~ SC_COMP_TCP;
617     x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
618
619     if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
620       {
621         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
622         return 0;
623       }
624
625     if (vjcomp)
626       {
627         if (ioctl (fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
628           {
629             syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
630             return 0;
631           }
632       }
633
634     return 1;
635   }
636
637 /*
638  * sifup - Config the interface up and enable IP packets to pass.
639  */
640
641 int sifup (int u)
642   {
643     struct ifreq ifr;
644
645     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
646     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
647       {
648         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
649         return 0;
650       }
651
652     ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
653     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
654       {
655         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
656         return 0;
657       }
658     return 1;
659   }
660
661 /*
662  * sifdown - Config the interface down and disable IP.
663  */
664
665 int sifdown (int u)
666   {
667     struct ifreq ifr;
668
669     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
670     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
671       {
672         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
673         return 0;
674       }
675
676     ifr.ifr_flags &= ~IFF_UP;
677     ifr.ifr_flags |= IFF_POINTOPOINT;
678     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
679       {
680         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
681         return 0;
682       }
683     return 1;
684   }
685
686 /*
687  * sifaddr - Config the interface IP addresses and netmask.
688  */
689
690 int sifaddr (int unit, int our_adr, int his_adr, int net_mask)
691   {
692     struct ifreq   ifr; 
693     struct rtentry rt;
694     
695     SET_SA_FAMILY (ifr.ifr_addr,    AF_INET); 
696     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); 
697     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); 
698
699     strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
700 /*
701  *  Set our IP address
702  */
703     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
704     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
705       {
706         if (errno != EEXIST)
707           {
708             syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m");
709           }
710         else
711           {
712             syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
713           }
714         return (0);
715       } 
716 /*
717  *  Set the gateway address
718  */
719     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
720     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
721       {
722         syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m"); 
723         return (0);
724       } 
725 /*
726  *  Set the netmask
727  */
728     if (net_mask != 0)
729       {
730         ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
731         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
732           {
733             syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m"); 
734             return (0);
735           } 
736       }
737 /*
738  *  Add the device route
739  */
740     memset (&rt, '\0', sizeof (rt));
741
742     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
743     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
744     rt.rt_dev = ifname;  /* MJC */
745
746     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
747     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
748     rt.rt_flags = RTF_UP | RTF_HOST;
749
750     if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
751       {
752         syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m");
753         return (0);
754       }
755     return 1;
756   }
757
758 /*
759  * cifaddr - Clear the interface IP addresses, and delete routes
760  * through the interface if possible.
761  */
762
763 int cifaddr (int unit, int our_adr, int his_adr)
764   {
765     struct rtentry rt;
766 /*
767  *  Delete the route through the device
768  */
769     memset (&rt, '\0', sizeof (rt));
770
771     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
772     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
773     rt.rt_dev = ifname;  /* MJC */
774
775     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
776     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
777     rt.rt_flags = RTF_UP | RTF_HOST;
778
779     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
780       {
781         syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m");
782         return (0);
783       }
784     return 1;
785   }
786
787 /*
788  * path_to_route - determine the path to the proc file system data
789  */
790
791 FILE *route_fd = (FILE *) 0;
792 static char route_buffer [100];
793
794 static char *path_to_route (void);
795 static int open_route_table (void);
796 static void close_route_table (void);
797 static int read_route_table (struct rtentry *rt);
798 static int defaultroute_exists (void);
799
800 /*
801  * path_to_route - find the path to the route tables in the proc file system
802  */
803
804 static char *path_to_route (void)
805   {
806     struct mntent *mntent;
807     FILE *fp;
808
809     fp = fopen (MOUNTED, "r");
810     if (fp != 0)
811       {
812         while ((mntent = getmntent (fp)) != 0)
813           {
814             if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) == 0)
815               {
816                 continue;
817               }
818
819             if (strcmp (mntent->mnt_type, "proc") == 0)
820               {
821                 strncpy (route_buffer, mntent->mnt_dir,
822                          sizeof (route_buffer)-10);
823                 route_buffer [sizeof (route_buffer)-10] = '\0';
824                 strcat (route_buffer, "/net/route");
825
826                 fclose (fp);
827                 return (route_buffer);
828               }
829           }
830         fclose (fp);
831       }
832     syslog (LOG_ERR, "proc file system not mounted");
833     return 0;
834   }
835
836 /*
837  * open_route_table - open the interface to the route table
838  */
839
840 static int open_route_table (void)
841   {
842     char *path;
843
844     if (route_fd != (FILE *) 0)
845       {
846         close_route_table();
847       }
848
849     path = path_to_route();
850     if (path == NULL)
851       {
852         return 0;
853       }
854
855     route_fd = fopen (path, "r");
856     if (route_fd == (FILE *) 0)
857       {
858         syslog (LOG_ERR, "can not open %s: %m", path);
859         return 0;
860       }
861
862     /* read and discard the header line. */
863     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
864       {
865         close_route_table();
866         return 0;
867       }
868     return 1;
869   }
870
871 /*
872  * close_route_table - close the interface to the route table
873  */
874
875 static void close_route_table (void)
876   {
877     if (route_fd != (FILE *) 0)
878       {
879         fclose (route_fd);
880         route_fd = (FILE *) 0;
881       }
882   }
883
884 /*
885  * read_route_table - read the next entry from the route table
886  */
887
888 static int read_route_table (struct rtentry *rt)
889   {
890     static char delims[] = " \t\n";
891     char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
892
893     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
894       {
895         return 0;
896       }
897
898     memset (rt, '\0', sizeof (struct rtentry));
899
900     dev_ptr  = strtok (route_buffer, delims); /* interface name */
901     dst_ptr  = strtok (NULL,         delims); /* destination address */
902     gw_ptr   = strtok (NULL,         delims); /* gateway */
903     flag_ptr = strtok (NULL,         delims); /* flags */
904
905     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
906       strtoul (dst_ptr, NULL, 16);
907
908     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
909       strtoul (gw_ptr, NULL, 16);
910
911     rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
912     rt->rt_dev   = dev_ptr;
913
914     return 1;
915   }
916
917 /*
918  * defaultroute_exists - determine if there is a default route
919  */
920
921 static int defaultroute_exists (void)
922   {
923     struct rtentry rt;
924     int    result = 0;
925
926     if (!open_route_table())
927       {
928         return 0;
929       }
930
931     while (read_route_table(&rt) != 0)
932       {
933         if (rt.rt_flags & RTF_UP == 0)
934           {
935             continue;
936           }
937
938         if (((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr == 0L)
939           {
940             syslog (LOG_ERR,
941                     "ppp not replacing existing default route to %s[%s]",
942                     rt.rt_dev,
943                     inet_ntoa (((struct sockaddr_in *) &rt.rt_gateway)->
944                                sin_addr.s_addr));
945             result = 1;
946             break;
947           }
948       }
949     close_route_table();
950     return result;
951   }
952
953 /*
954  * sifdefaultroute - assign a default route through the address given.
955  */
956
957 int sifdefaultroute (int unit, int gateway)
958   {
959     struct rtentry rt;
960
961     if (defaultroute_exists())
962       {
963         return 0;
964       }
965
966     memset (&rt, '\0', sizeof (rt));
967     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
968     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
969     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
970     
971     rt.rt_flags = RTF_UP | RTF_GATEWAY;
972     if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
973       {
974         syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m");
975         return 0;
976       }
977     return 1;
978   }
979
980 /*
981  * cifdefaultroute - delete a default route through the address given.
982  */
983
984 int cifdefaultroute (int unit, int gateway)
985   {
986     struct rtentry rt;
987   
988     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
989     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
990     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
991     
992     rt.rt_flags = RTF_UP | RTF_GATEWAY;
993     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
994       {
995         syslog (LOG_ERR, "default route ioctl(SIOCDELRT): %m");
996         return 0;
997       }
998     return 1;
999   }
1000
1001 /*
1002  * sifproxyarp - Make a proxy ARP entry for the peer.
1003  */
1004
1005 int sifproxyarp (int unit, u_int32_t his_adr)
1006   {
1007     struct arpreq arpreq;
1008
1009     memset (&arpreq, '\0', sizeof(arpreq));
1010 /*
1011  * Get the hardware address of an interface on the same subnet
1012  * as our local address.
1013  */
1014     if (!get_ether_addr(his_adr, &arpreq.arp_ha))
1015       {
1016         syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1017         return 0;
1018       }
1019     
1020     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1021     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1022     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1023     
1024     if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0)
1025       {
1026         syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1027         return 0;
1028       }
1029     return 1;
1030   }
1031
1032 /*
1033  * cifproxyarp - Delete the proxy ARP entry for the peer.
1034  */
1035
1036 int cifproxyarp (int unit, u_int32_t his_adr)
1037   {
1038     struct arpreq arpreq;
1039   
1040     memset (&arpreq, '\0', sizeof(arpreq));
1041     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1042     
1043     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1044     if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0)
1045       {
1046         syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1047         return 0;
1048       }
1049     return 1;
1050   }
1051      
1052 /*
1053  * get_ether_addr - get the hardware address of an interface on the
1054  * the same subnet as ipaddr.
1055  */
1056
1057 int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr)
1058   {
1059     struct ifreq *ifr, *ifend, *ifp;
1060     int i;
1061     u_int32_t ina, mask;
1062     struct sockaddr_dl *dla;
1063     struct ifreq ifreq;
1064     struct ifconf ifc;
1065     struct ifreq ifs[MAX_IFS];
1066     
1067     ifc.ifc_len = sizeof(ifs);
1068     ifc.ifc_req = ifs;
1069     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1070       {
1071         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1072         return 0;
1073       }
1074     MAINDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
1075                 ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
1076 /*
1077  * Scan through looking for an interface with an Internet
1078  * address on the same subnet as `ipaddr'.
1079  */
1080     ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1081     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1082       {
1083         if (ifr->ifr_addr.sa_family == AF_INET)
1084           {
1085             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1086             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1087             MAINDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
1088                         ifreq.ifr_name));
1089 /*
1090  * Check that the interface is up, and not point-to-point
1091  * or loopback.
1092  */
1093             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1094               {
1095                 continue;
1096               }
1097             if ((ifreq.ifr_flags &
1098                  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1099                 != (IFF_UP|IFF_BROADCAST))
1100               {
1101                 continue;
1102               }
1103 /*
1104  * Get its netmask and check that it's on the right subnet.
1105  */
1106             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1107               {
1108                 continue;
1109               }
1110             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1111             MAINDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
1112                         ip_ntoa(ina), ntohl(mask)));
1113             if (((ipaddr ^ ina) & mask) != 0)
1114               {
1115                 continue;
1116               }
1117             break;
1118           }
1119       }
1120     
1121     if (ifr >= ifend)
1122       {
1123         return 0;
1124       }
1125
1126     syslog(LOG_INFO, "found interface %s for proxy arp", ifreq.ifr_name);
1127 /*
1128  * Now get the hardware address.
1129  */
1130     if (ioctl (sockfd, SIOCGIFHWADDR, &ifreq) < 0)
1131       {
1132         syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m", ifreq.ifr_name);
1133         return 0;
1134       }
1135
1136     hwaddr->sa_family = ARPHRD_ETHER;
1137     memcpy (&hwaddr->sa_data, &ifreq.ifr_hwaddr.sa_data, ETH_ALEN);
1138
1139     MAINDEBUG ((LOG_DEBUG,
1140                 "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x",
1141                 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1142                 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1143                 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1144                 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1145                 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1146                 (int) ((unsigned char *) &hwaddr->sa_data)[5]));
1147     return 1;
1148   }
1149
1150 /*
1151  * Internal routine to decode the version.modification.patch level
1152  */
1153
1154 static void decode_version (char *buf, int *version,
1155                             int *modification, int *patch)
1156   {
1157
1158     *version      = (int) strtoul (buf, &buf, 10);
1159     *modification = 0;
1160     *patch        = 0;
1161     
1162     if (*buf == '.')
1163       {
1164         ++buf;
1165         *modification = (int) strtoul (buf, &buf, 10);
1166         if (*buf == '.')
1167           {
1168             ++buf;
1169             *patch = (int) strtoul (buf, &buf, 10);
1170           }
1171       }
1172     
1173     if (*buf != '\0')
1174       {
1175         *version      =
1176         *modification =
1177         *patch        = 0;
1178       }
1179   }
1180
1181 /*
1182  * ppp_available - check whether the system has any ppp interfaces
1183  * (in fact we check whether we can do an ioctl on ppp0).
1184  */
1185
1186 int ppp_available(void)
1187   {
1188     int s, ok;
1189     struct ifreq ifr;
1190     int my_version,     my_modification,     my_patch;
1191 /*
1192  * Open a socket for doing the ioctl operations.
1193  */    
1194     s = socket(AF_INET, SOCK_DGRAM, 0);
1195     if (s < 0)
1196       {
1197         return 0;
1198       }
1199     
1200     strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1201     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1202 /*
1203  * Ensure that the hardware address is for PPP and not something else
1204  */
1205     if (ok != 0)
1206       {
1207         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
1208       }
1209
1210     if (ok != 0 && ifr.ifr_hwaddr.sa_family != ARPHRD_PPP)
1211       {
1212         ok = 0;
1213       }
1214 /*
1215  *  This is the PPP device. Validate the version of the driver at this
1216  *  point to ensure that this program will work with the driver.
1217  */
1218     if (ok != 0)
1219       {
1220         char   abBuffer [1024];
1221         int    size;
1222
1223         ifr.ifr_data = abBuffer;
1224         size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
1225         ok   = size >= 0;
1226
1227         if (ok != 0)
1228           {
1229             decode_version (abBuffer,
1230                             &driver_version,
1231                             &driver_modification,
1232                             &driver_patch);
1233           }
1234       }
1235     
1236     if (ok == 0)
1237       {
1238         driver_version      =
1239         driver_modification =
1240         driver_patch        = 0;
1241       }
1242 /*
1243  * Validate the version of the driver against the version that we used.
1244  */
1245     decode_version (PPP_VERSION,
1246                     &my_version,
1247                     &my_modification,
1248                     &my_patch);
1249
1250     /* The version numbers must match */
1251     if (driver_version != my_version)
1252       {
1253         ok = 0;
1254       }
1255       
1256     /* The modification levels must be legal */
1257     if (driver_modification < my_modification)
1258       {
1259         ok = 0;
1260       }
1261
1262     if (ok == 0)
1263       {
1264         fprintf(stderr, "Sorry - PPP driver version %d.%d.%d is out of date\n",
1265                 driver_version, driver_modification, driver_patch);
1266       }
1267     
1268     close(s);
1269     return ok;
1270   }
1271
1272 int logwtmp (char *line, char *name, char *host)
1273   {
1274     struct utmp ut;
1275     int    mode;
1276 /*
1277  * Control the 'mesg' function based upon the state of the logon
1278  * operation.
1279  */
1280     mode = (*name != '\0') ? 0600 : 0622;
1281     if (chmod (devnam, mode) < 0)
1282       {
1283         syslog (LOG_ERR, "chmod(\"%s\", 0%o): %m", devnam, mode);
1284       }
1285 /*
1286  * Update the signon database for users.
1287  */
1288     memset (&ut, 0, sizeof (ut));
1289     (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1290     (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1291     (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1292     (void)time(&ut.ut_time);
1293         
1294     pututline (&ut);            /* Write the line to the proper place */
1295     endutent();                 /* Indicate operation is complete */
1296   }
1297
1298 /*
1299  * Code for locking/unlocking the serial device.
1300  * This code is derived from chat.c.
1301  */
1302
1303 #define LOCK_PREFIX     "/var/lock/LCK.."
1304
1305 /*
1306  * lock - create a lock file for the named device
1307  */
1308 int
1309 lock(dev)
1310     char *dev;
1311 {
1312     char hdb_lock_buffer[12];
1313     int fd, pid, n;
1314     char *p;
1315
1316     if ((p = strrchr(dev, '/')) != NULL)
1317         dev = p + 1;
1318     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1319     if (lock_file == NULL)
1320         novm("lock file name");
1321     strcat(strcpy(lock_file, LOCK_PREFIX), dev);
1322
1323     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
1324         if (errno == EEXIST
1325             && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
1326             /* Read the lock file to find out who has the device locked */
1327             n = read(fd, hdb_lock_buffer, 11);
1328             if (n > 0) {
1329                 hdb_lock_buffer[n] = 0;
1330                 sscanf (hdb_lock_buffer, " %d", &pid);
1331             }
1332             if (n <= 0) {
1333                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1334                 close(fd);
1335             } else {
1336                 if (kill(pid, 0) == -1 && errno == ESRCH) {
1337                     /* pid no longer exists - remove the lock file */
1338                     if (unlink(lock_file) == 0) {
1339                         close(fd);
1340                         syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1341                                dev, pid);
1342                         continue;
1343                     } else
1344                         syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
1345                                dev);
1346                 } else
1347                     syslog(LOG_NOTICE, "Device %s is locked by pid %d",
1348                            dev, pid);
1349             }
1350             close(fd);
1351         } else
1352             syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1353         free(lock_file);
1354         lock_file = NULL;
1355         return -1;
1356     }
1357
1358     sprintf(hdb_lock_buffer, "%010d\n", getpid());
1359     write(fd, hdb_lock_buffer, 11);
1360
1361     close(fd);
1362     return 0;
1363 }
1364
1365 /*
1366  * unlock - remove our lockfile
1367  */
1368 unlock()
1369 {
1370     if (lock_file) {
1371         unlink(lock_file);
1372         free(lock_file);
1373         lock_file = NULL;
1374     }
1375 }