]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-linux.c
Fix from Steve Tate.
[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     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
638     ifr.ifr_mtu = mtu;
639
640     if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
641       {
642         syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
643         quit();
644       }
645     
646     MAINDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
647     if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
648       {
649         syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
650         quit();
651       }
652     
653     x = get_flags();
654     x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
655     x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
656     set_flags(x);
657   }
658
659 /*
660  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
661  */
662
663 void ppp_set_xaccm (int unit, ext_accm accm)
664   {
665     MAINDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
666                 accm[0], accm[1], accm[2], accm[3]));
667
668     if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
669       {
670         syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
671       }
672   }
673
674 /*
675  * ppp_recv_config - configure the receive-side characteristics of
676  * the ppp interface.
677  */
678
679 void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
680   {
681     u_int x;
682
683     MAINDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
684 /*
685  * If we were called because the link has gone down then there is nothing
686  * which may be done. Just return without incident.
687  */
688     if (!still_ppp())
689       {
690         return;
691       }
692 /*
693  * Set the receiver parameters
694  */
695     if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
696       {
697         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
698       }
699
700     MAINDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
701     if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
702       {
703         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
704         quit();
705       }
706
707     x = get_flags();
708     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
709     set_flags (x);
710   }
711
712 /*
713  * ccp_test - ask kernel whether a given compression method
714  * is acceptable for use.
715  */
716
717 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
718   {
719     struct ppp_option_data data;
720
721     data.ptr      = opt_ptr;
722     data.length   = opt_len;
723     data.transmit = for_transmit;
724
725     return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
726   }
727
728 /*
729  * ccp_flags_set - inform kernel about the current state of CCP.
730  */
731
732 void ccp_flags_set (int unit, int isopen, int isup)
733   {
734     if (still_ppp())
735       {
736         int x = get_flags();
737         x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
738         x = isup?   x | SC_CCP_UP   : x &~ SC_CCP_UP;
739         set_flags (x);
740       }
741   }
742
743 /*
744  * ccp_fatal_error - returns 1 if decompression was disabled as a
745  * result of an error detected after decompression of a packet,
746  * 0 otherwise.  This is necessary because of patent nonsense.
747  */
748
749 int ccp_fatal_error (int unit)
750   {
751     int x = get_flags();
752
753     return x & SC_DC_FERROR;
754   }
755
756 /*
757  * sifvjcomp - config tcp header compression
758  */
759
760 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
761   {
762     u_int x = get_flags();
763
764     if (vjcomp)
765       {
766         if (ioctl (fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
767           {
768             syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
769             vjcomp = 0;
770           }
771       }
772
773     x = vjcomp  ? x | SC_COMP_TCP     : x &~ SC_COMP_TCP;
774     x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
775     set_flags (x);
776
777     return 1;
778   }
779
780 /*
781  * sifup - Config the interface up and enable IP packets to pass.
782  */
783
784 int sifup (int u)
785   {
786     struct ifreq ifr;
787
788     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
789     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
790       {
791         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
792         return 0;
793       }
794
795     ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
796     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
797       {
798         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
799         return 0;
800       }
801     return 1;
802   }
803
804 /*
805  * sifdown - Config the interface down and disable IP.
806  */
807
808 int sifdown (int u)
809   {
810     struct ifreq ifr;
811
812     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
813     if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
814       {
815         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
816         return 0;
817       }
818
819     ifr.ifr_flags &= ~IFF_UP;
820     ifr.ifr_flags |= IFF_POINTOPOINT;
821     if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
822       {
823         syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
824         return 0;
825       }
826     return 1;
827   }
828
829 /*
830  * sifaddr - Config the interface IP addresses and netmask.
831  */
832
833 int sifaddr (int unit, int our_adr, int his_adr, int net_mask)
834   {
835     struct ifreq   ifr; 
836     struct rtentry rt;
837     
838     SET_SA_FAMILY (ifr.ifr_addr,    AF_INET); 
839     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); 
840     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); 
841
842     strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
843 /*
844  *  Set our IP address
845  */
846     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
847     if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
848       {
849         if (errno != EEXIST)
850           {
851             syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m");
852           }
853         else
854           {
855             syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
856           }
857         return (0);
858       } 
859 /*
860  *  Set the gateway address
861  */
862     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
863     if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
864       {
865         syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m"); 
866         return (0);
867       } 
868 /*
869  *  Set the netmask
870  */
871     if (net_mask != 0)
872       {
873         ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
874         if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
875           {
876             syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m"); 
877             return (0);
878           } 
879       }
880 /*
881  *  Add the device route
882  */
883     memset (&rt, '\0', sizeof (rt));
884
885     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
886     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
887     rt.rt_dev = ifname;  /* MJC */
888
889     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
890     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
891     rt.rt_flags = RTF_UP | RTF_HOST;
892
893     if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
894       {
895         syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m");
896         return (0);
897       }
898     return 1;
899   }
900
901 /*
902  * cifaddr - Clear the interface IP addresses, and delete routes
903  * through the interface if possible.
904  */
905
906 int cifaddr (int unit, int our_adr, int his_adr)
907   {
908     struct rtentry rt;
909 /*
910  *  Delete the route through the device
911  */
912     memset (&rt, '\0', sizeof (rt));
913
914     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
915     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
916     rt.rt_dev = ifname;  /* MJC */
917
918     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
919     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
920     rt.rt_flags = RTF_UP | RTF_HOST;
921
922     if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
923       {
924         syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m");
925         return (0);
926       }
927     return 1;
928   }
929
930 /*
931  * path_to_route - determine the path to the proc file system data
932  */
933
934 FILE *route_fd = (FILE *) 0;
935 static char route_buffer [100];
936
937 static char *path_to_route (void);
938 static int open_route_table (void);
939 static void close_route_table (void);
940 static int read_route_table (struct rtentry *rt);
941 static int defaultroute_exists (void);
942
943 /*
944  * path_to_route - find the path to the route tables in the proc file system
945  */
946
947 static char *path_to_route (void)
948   {
949     struct mntent *mntent;
950     FILE *fp;
951
952     fp = fopen (MOUNTED, "r");
953     if (fp != 0)
954       {
955         mntent = getmntent (fp);
956         while (mntent != (struct mntent *) 0)
957           {
958             if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) != 0)
959               {
960                 if (strcmp (mntent->mnt_type, "proc") == 0)
961                   {
962                     strncpy (route_buffer, mntent->mnt_dir,
963                              sizeof (route_buffer)-10);
964                     route_buffer [sizeof (route_buffer)-10] = '\0';
965                     strcat (route_buffer, "/net/route");
966                     
967                     fclose (fp);
968                     return (route_buffer);
969                   }
970               }
971             mntent = getmntent (fp);
972           }
973         fclose (fp);
974       }
975
976     syslog (LOG_ERR, "proc file system not mounted");
977     return 0;
978   }
979
980 /*
981  * open_route_table - open the interface to the route table
982  */
983
984 static int open_route_table (void)
985   {
986     char *path;
987
988     if (route_fd != (FILE *) 0)
989       {
990         close_route_table();
991       }
992
993     path = path_to_route();
994     if (path == NULL)
995       {
996         return 0;
997       }
998
999     route_fd = fopen (path, "r");
1000     if (route_fd == (FILE *) 0)
1001       {
1002         syslog (LOG_ERR, "can not open %s: %m", path);
1003         return 0;
1004       }
1005
1006     /* read and discard the header line. */
1007     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
1008       {
1009         close_route_table();
1010         return 0;
1011       }
1012     return 1;
1013   }
1014
1015 /*
1016  * close_route_table - close the interface to the route table
1017  */
1018
1019 static void close_route_table (void)
1020   {
1021     if (route_fd != (FILE *) 0)
1022       {
1023         fclose (route_fd);
1024         route_fd = (FILE *) 0;
1025       }
1026   }
1027
1028 /*
1029  * read_route_table - read the next entry from the route table
1030  */
1031
1032 static int read_route_table (struct rtentry *rt)
1033   {
1034     static char delims[] = " \t\n";
1035     char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
1036
1037     if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
1038       {
1039         return 0;
1040       }
1041
1042     memset (rt, '\0', sizeof (struct rtentry));
1043
1044     dev_ptr  = strtok (route_buffer, delims); /* interface name */
1045     dst_ptr  = strtok (NULL,         delims); /* destination address */
1046     gw_ptr   = strtok (NULL,         delims); /* gateway */
1047     flag_ptr = strtok (NULL,         delims); /* flags */
1048
1049     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
1050       strtoul (dst_ptr, NULL, 16);
1051
1052     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
1053       strtoul (gw_ptr, NULL, 16);
1054
1055     rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
1056     rt->rt_dev   = dev_ptr;
1057
1058     return 1;
1059   }
1060
1061 /*
1062  * defaultroute_exists - determine if there is a default route
1063  */
1064
1065 static int defaultroute_exists (void)
1066   {
1067     struct rtentry rt;
1068     int    result = 0;
1069
1070     if (!open_route_table())
1071       {
1072         return 0;
1073       }
1074
1075     while (read_route_table(&rt) != 0)
1076       {
1077         if (rt.rt_flags & RTF_UP == 0)
1078           {
1079             continue;
1080           }
1081
1082         if (((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr == 0L)
1083           {
1084             syslog (LOG_ERR,
1085                     "ppp not replacing existing default route to %s[%s]",
1086                     rt.rt_dev,
1087                     inet_ntoa (((struct sockaddr_in *) &rt.rt_gateway)->
1088                                sin_addr.s_addr));
1089             result = 1;
1090             break;
1091           }
1092       }
1093
1094     close_route_table();
1095     return result;
1096   }
1097
1098 /*
1099  * sifdefaultroute - assign a default route through the address given.
1100  */
1101
1102 int sifdefaultroute (int unit, int gateway)
1103   {
1104     struct rtentry rt;
1105
1106     if (has_default_route == 0)
1107       {
1108         if (defaultroute_exists())
1109           {
1110             return 0;
1111           }
1112
1113         memset (&rt, '\0', sizeof (rt));
1114         SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1115         SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1116         ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1117     
1118         rt.rt_flags = RTF_UP | RTF_GATEWAY;
1119         if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
1120           {
1121             syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m");
1122             return 0;
1123           }
1124       }
1125     has_default_route = 1;
1126     return 1;
1127   }
1128
1129 /*
1130  * cifdefaultroute - delete a default route through the address given.
1131  */
1132
1133 int cifdefaultroute (int unit, int gateway)
1134   {
1135     struct rtentry rt;
1136
1137     if (has_default_route)
1138       {
1139         SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1140         SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1141         ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1142     
1143         rt.rt_flags = RTF_UP | RTF_GATEWAY;
1144         if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
1145           {
1146             if (errno != ENOENT || still_ppp())
1147               {
1148                 syslog (LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1149                 return 0;
1150               }
1151           }
1152       }
1153     has_default_route = 0;
1154     return 1;
1155   }
1156
1157 /*
1158  * sifproxyarp - Make a proxy ARP entry for the peer.
1159  */
1160
1161 int sifproxyarp (int unit, u_int32_t his_adr)
1162   {
1163     struct arpreq arpreq;
1164
1165     if (has_proxy_arp == 0)
1166       {
1167         memset (&arpreq, '\0', sizeof(arpreq));
1168 /*
1169  * Get the hardware address of an interface on the same subnet
1170  * as our local address.
1171  */
1172         if (!get_ether_addr(his_adr, &arpreq.arp_ha))
1173           {
1174             syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1175             return 0;
1176           }
1177     
1178         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1179         ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1180         arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1181         
1182         if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0)
1183           {
1184             syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1185             return 0;
1186           }
1187       }
1188
1189     has_proxy_arp = 1;
1190     return 1;
1191   }
1192
1193 /*
1194  * cifproxyarp - Delete the proxy ARP entry for the peer.
1195  */
1196
1197 int cifproxyarp (int unit, u_int32_t his_adr)
1198   {
1199     struct arpreq arpreq;
1200
1201     if (has_proxy_arp == 1)
1202       {
1203         memset (&arpreq, '\0', sizeof(arpreq));
1204         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1205     
1206         ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1207         if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0)
1208           {
1209             syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1210             return 0;
1211           }
1212       }
1213     has_proxy_arp = 0;
1214     return 1;
1215   }
1216      
1217 /*
1218  * get_ether_addr - get the hardware address of an interface on the
1219  * the same subnet as ipaddr.
1220  */
1221
1222 int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr)
1223   {
1224     struct ifreq *ifr, *ifend, *ifp;
1225     int i;
1226     u_int32_t ina, mask;
1227     struct sockaddr_dl *dla;
1228     struct ifreq ifreq;
1229     struct ifconf ifc;
1230     struct ifreq ifs[MAX_IFS];
1231     
1232     ifc.ifc_len = sizeof(ifs);
1233     ifc.ifc_req = ifs;
1234     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1235       {
1236         syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1237         return 0;
1238       }
1239
1240     MAINDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
1241                 ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
1242 /*
1243  * Scan through looking for an interface with an Internet
1244  * address on the same subnet as `ipaddr'.
1245  */
1246     ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1247     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1248       {
1249         if (ifr->ifr_addr.sa_family == AF_INET)
1250           {
1251             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1252             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1253             MAINDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
1254                         ifreq.ifr_name));
1255 /*
1256  * Check that the interface is up, and not point-to-point
1257  * nor loopback.
1258  */
1259             if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1260               {
1261                 continue;
1262               }
1263
1264             if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1265               {
1266                 continue;
1267               }
1268 /*
1269  * Get its netmask and check that it's on the right subnet.
1270  */
1271             if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1272               {
1273                 continue;
1274               }
1275
1276             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1277             MAINDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
1278                         ip_ntoa(ina), ntohl(mask)));
1279
1280             if (((ipaddr ^ ina) & mask) != 0)
1281               {
1282                 continue;
1283               }
1284             break;
1285           }
1286       }
1287     
1288     if (ifr >= ifend)
1289       {
1290         return 0;
1291       }
1292
1293     syslog(LOG_INFO, "found interface %s for proxy arp", ifreq.ifr_name);
1294 /*
1295  * Now get the hardware address.
1296  */
1297 #if 0  /* old code */
1298     if (ioctl (sockfd, SIOCGIFHWADDR, &ifreq) < 0)
1299       {
1300         syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m", ifreq.ifr_name);
1301         return 0;
1302       }
1303
1304     hwaddr->sa_family = ARPHRD_ETHER;
1305     memcpy (&hwaddr->sa_data, &ifreq.ifr_hwaddr.sa_data, ETH_ALEN);
1306
1307     MAINDEBUG ((LOG_DEBUG,
1308                 "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x",
1309                 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1310                 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1311                 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1312                 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1313                 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1314                 (int) ((unsigned char *) &hwaddr->sa_data)[5]));
1315 #else  /* the 'proper' code */
1316     memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
1317     if (ioctl (sockfd, SIOCGIFHWADDR, &ifreq) < 0)
1318       {
1319         syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m", ifreq.ifr_name);
1320         return 0;
1321       }
1322
1323     memcpy (hwaddr,
1324             &ifreq.ifr_hwaddr,
1325             sizeof (struct sockaddr));
1326
1327     MAINDEBUG ((LOG_DEBUG,
1328            "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1329                 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1330                 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1331                 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1332                 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1333                 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1334                 (int) ((unsigned char *) &hwaddr->sa_data)[5],
1335                 (int) ((unsigned char *) &hwaddr->sa_data)[6],
1336                 (int) ((unsigned char *) &hwaddr->sa_data)[7]));
1337 #endif
1338     return 1;
1339   }
1340
1341 /*
1342  * Return user specified netmask, modified by any mask we might determine
1343  * for address `addr' (in network byte order).
1344  * Here we scan through the system's list of interfaces, looking for
1345  * any non-point-to-point interfaces which might appear to be on the same
1346  * network as `addr'.  If we find any, we OR in their netmask to the
1347  * user-specified netmask.
1348  */
1349
1350 u_int32_t GetMask (u_int32_t addr)
1351   {
1352     u_int32_t mask, nmask, ina;
1353     struct ifreq *ifr, *ifend, ifreq;
1354     struct ifconf ifc;
1355     struct ifreq ifs[MAX_IFS];
1356
1357     addr = ntohl(addr);
1358     
1359     if (IN_CLASSA(addr))        /* determine network mask for address class */
1360       {
1361         nmask = IN_CLASSA_NET;
1362       }
1363     else
1364       {
1365         if (IN_CLASSB(addr))
1366           {
1367             nmask = IN_CLASSB_NET;
1368           }
1369         else
1370           {
1371             nmask = IN_CLASSC_NET;
1372           }
1373       }
1374     
1375     /* class D nets are disallowed by bad_ip_adrs */
1376     mask = netmask | htonl(nmask);
1377 /*
1378  * Scan through the system's network interfaces.
1379  */
1380     ifc.ifc_len = sizeof(ifs);
1381     ifc.ifc_req = ifs;
1382     if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1383       {
1384         syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1385         return mask;
1386       }
1387     
1388     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1389     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1390       {
1391 /*
1392  * Check the interface's internet address.
1393  */
1394         if (ifr->ifr_addr.sa_family != AF_INET)
1395           {
1396             continue;
1397           }
1398         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1399         if (((ntohl(ina) ^ addr) & nmask) != 0)
1400           {
1401             continue;
1402           }
1403 /*
1404  * Check that the interface is up, and not point-to-point nor loopback.
1405  */
1406         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1407         if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1408           {
1409             continue;
1410           }
1411         
1412         if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1413           {
1414             continue;
1415           }
1416 /*
1417  * Get its netmask and OR it into our mask.
1418  */
1419         if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1420           {
1421             continue;
1422           }
1423         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1424         break;
1425       }
1426     return mask;
1427   }
1428
1429 /*
1430  * Internal routine to decode the version.modification.patch level
1431  */
1432
1433 static void decode_version (char *buf, int *version,
1434                             int *modification, int *patch)
1435   {
1436     *version      = (int) strtoul (buf, &buf, 10);
1437     *modification = 0;
1438     *patch        = 0;
1439     
1440     if (*buf == '.')
1441       {
1442         ++buf;
1443         *modification = (int) strtoul (buf, &buf, 10);
1444         if (*buf == '.')
1445           {
1446             ++buf;
1447             *patch = (int) strtoul (buf, &buf, 10);
1448           }
1449       }
1450     
1451     if (*buf != '\0')
1452       {
1453         *version      =
1454         *modification =
1455         *patch        = 0;
1456       }
1457   }
1458
1459 /*
1460  * Procedure to determine if the PPP line dicipline is registered.
1461  */
1462
1463 int
1464 ppp_registered(void)
1465   {
1466     int local_fd;
1467     int ppp_disc  = N_PPP;
1468     int init_disc = -1;
1469     int initfdflags;
1470
1471     local_fd = open(devnam, O_NONBLOCK | O_RDWR, 0);
1472     if (local_fd < 0)
1473       {
1474         syslog(LOG_ERR, "Failed to open %s: %m", devnam);
1475         return 0;
1476       }
1477
1478     initfdflags = fcntl(local_fd, F_GETFL);
1479     if (initfdflags == -1)
1480       {
1481         syslog(LOG_ERR, "Couldn't get device fd flags: %m");
1482         close (local_fd);
1483         return 0;
1484       }
1485
1486     initfdflags &= ~O_NONBLOCK;
1487     fcntl(local_fd, F_SETFL, initfdflags);
1488 /*
1489  * Read the initial line dicipline and try to put the device into the
1490  * PPP dicipline.
1491  */
1492     if (ioctl(local_fd, TIOCGETD, &init_disc) < 0)
1493       {
1494         syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
1495         close (local_fd);
1496         return 0;
1497       }
1498     
1499     if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0)
1500       {
1501         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1502         close (local_fd);
1503         return 0;
1504       }
1505     
1506     if (ioctl(local_fd, TIOCSETD, &init_disc) < 0)
1507       {
1508         syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1509         close (local_fd);
1510         return 0;
1511       }
1512     
1513     close (local_fd);
1514     return 1;
1515   }
1516
1517 /*
1518  * ppp_available - check whether the system has any ppp interfaces
1519  * (in fact we check whether we can do an ioctl on ppp0).
1520  */
1521
1522 int ppp_available(void)
1523   {
1524     int s, ok;
1525     struct ifreq ifr;
1526     char   abBuffer [1024];
1527     int    size;
1528     int    my_version, my_modification, my_patch;
1529 /*
1530  * Open a socket for doing the ioctl operations.
1531  */    
1532     s = socket(AF_INET, SOCK_DGRAM, 0);
1533     if (s < 0)
1534       {
1535         return 0;
1536       }
1537     
1538     strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1539     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1540 /*
1541  * If the device did not exist then attempt to create one by putting the
1542  * current tty into the PPP discipline. If this works then obtain the
1543  * flags for the device again.
1544  */
1545     if (!ok)
1546       {
1547         if (ppp_registered())
1548           {
1549             strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1550             ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1551           }
1552       }
1553 /*
1554  * Ensure that the hardware address is for PPP and not something else
1555  */
1556     if (ok)
1557       {
1558         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
1559       }
1560
1561     if (ok && ifr.ifr_hwaddr.sa_family != ARPHRD_PPP)
1562       {
1563         ok = 0;
1564       }
1565
1566     if (!ok)
1567       {
1568         return 0;
1569       }
1570 /*
1571  *  This is the PPP device. Validate the version of the driver at this
1572  *  point to ensure that this program will work with the driver.
1573  */
1574     ifr.ifr_data = abBuffer;
1575     size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
1576     ok   = size >= 0;
1577
1578     if (ok)
1579       {
1580         decode_version (abBuffer,
1581                         &driver_version,
1582                         &driver_modification,
1583                         &driver_patch);
1584       }
1585     
1586     if (!ok)
1587       {
1588         driver_version      =
1589         driver_modification =
1590         driver_patch        = 0;
1591       }
1592 /*
1593  * Validate the version of the driver against the version that we used.
1594  */
1595     decode_version (PPP_VERSION,
1596                     &my_version,
1597                     &my_modification,
1598                     &my_patch);
1599
1600     /* The version numbers must match */
1601     if (driver_version != my_version)
1602       {
1603         ok = 0;
1604       }
1605       
1606     /* The modification levels must be legal */
1607     if (driver_modification < my_modification)
1608       {
1609         ok = 0;
1610       }
1611
1612     if (!ok)
1613       {
1614         fprintf(stderr, "Sorry - PPP driver version %d.%d.%d is out of date\n",
1615                 driver_version, driver_modification, driver_patch);
1616         close (s);
1617         exit (1);
1618       }
1619     
1620     close(s);
1621     return ok;
1622   }
1623
1624 /*
1625  * Update the wtmp file with the appropriate user name and tty device.
1626  */
1627
1628 int logwtmp (char *line, char *name, char *host)
1629   {
1630     struct utmp ut;
1631     int    mode;
1632 /*
1633  * Control the 'mesg' function based upon the state of the logon
1634  * operation.
1635  */
1636     mode = (*name != '\0') ? 0600 : 0622;
1637     if (chmod (devnam, mode) < 0)
1638       {
1639         syslog (LOG_ERR, "chmod(\"%s\", 0%o): %m", devnam, mode);
1640       }
1641 /*
1642  * Update the signon database for users.
1643  */
1644     memset (&ut, 0, sizeof (ut));
1645     (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1646     (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1647     (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1648     (void)time(&ut.ut_time);
1649         
1650     pututline (&ut);            /* Write the line to the proper place */
1651     endutent();                 /* Indicate operation is complete */
1652   }
1653
1654 /*
1655  * Code for locking/unlocking the serial device.
1656  * This code is derived from chat.c.
1657  */
1658
1659 #define LOCK_PREFIX     "/var/lock/LCK.."
1660
1661 /*
1662  * lock - create a lock file for the named device
1663  */
1664
1665 int lock (char *dev)
1666   {
1667     char hdb_lock_buffer[12];
1668     int fd, pid, n;
1669     char *p;
1670
1671     p = strrchr(dev, '/');
1672     if (p != NULL)
1673       {
1674         dev = ++p;
1675       }
1676
1677     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1678     if (lock_file == NULL)
1679       {
1680         novm("lock file name");
1681       }
1682
1683     strcpy (lock_file, LOCK_PREFIX);
1684     strcat (lock_file, dev);
1685 /*
1686  * Attempt to create the lock file at this point.
1687  */
1688     while (1)
1689       {
1690         fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644);
1691         if (fd >= 0)
1692           {
1693             sprintf(hdb_lock_buffer, "%010d\n", getpid());
1694             write(fd, hdb_lock_buffer, 11);
1695             close(fd);
1696             return 0;
1697           }
1698 /*
1699  * If the file exists then check to see if the pid is stale
1700  */
1701         if (errno == EEXIST)
1702           {
1703             fd = open(lock_file, O_RDONLY, 0);
1704             if (fd < 0)
1705               {
1706                 if (errno == ENOENT) /* This is just a timing problem. */
1707                   {
1708                     continue;
1709                   }
1710                 break;
1711               }
1712
1713             /* Read the lock file to find out who has the device locked */
1714             n = read (fd, hdb_lock_buffer, 11);
1715             close (fd);
1716             if (n < 0)
1717               {
1718                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1719                 break;
1720               }
1721
1722             if (n == 0)
1723               {
1724                 unlink (lock_file);
1725                 syslog (LOG_NOTICE, "Removed stale lock on %s", lock_file);
1726                 continue;
1727               }
1728
1729             hdb_lock_buffer[n] = '\0';
1730             sscanf (hdb_lock_buffer, " %d", &pid);
1731
1732             if (kill(pid, 0) == -1 && errno == ESRCH)
1733               {
1734                 /* pid no longer exists - remove the lock file */
1735                 if (unlink (lock_file) == 0)
1736                   {
1737                     syslog (LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1738                             dev, pid);
1739                     continue;
1740                   }
1741               }
1742
1743             syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, pid);
1744             break;
1745           }
1746
1747         syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1748         break;
1749       }
1750
1751     free(lock_file);
1752     lock_file = NULL;
1753     return -1;
1754 }
1755
1756 /*
1757  * unlock - remove our lockfile
1758  */
1759
1760 void unlock(void)
1761   {
1762     if (lock_file)
1763       {
1764         unlink(lock_file);
1765         free(lock_file);
1766         lock_file = NULL;
1767       }
1768   }