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