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