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