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