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