]> git.ozlabs.org Git - ppp.git/blob - pppd/sys-linux.c
not used any more
[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 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/time.h>
25 #include <sys/errno.h>
26 #include <sys/file.h>
27 #include <sys/stat.h>
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <syslog.h>
32 #include <string.h>
33 #include <time.h>
34 #include <memory.h>
35 #include <utmp.h>
36 #include <mntent.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <ctype.h>
40
41 /* This is in netdevice.h. However, this compile will fail miserably if
42    you attempt to include netdevice.h because it has so many references
43    to __memcpy functions which it should not attempt to do. So, since I
44    really don't use it, but it must be defined, define it now. */
45
46 #ifndef MAX_ADDR_LEN
47 #define MAX_ADDR_LEN 7
48 #endif
49
50 #include <net/if.h>
51 #include <linux/ppp_defs.h>
52 #include <net/if_arp.h>
53 #include <linux/if_ppp.h>
54 #include <net/route.h>
55 #include <linux/if_ether.h>
56 #include <netinet/in.h>
57
58 #include "pppd.h"
59 #include "fsm.h"
60 #include "ipcp.h"
61
62 #ifdef IPX_CHANGE
63 #include "ipxcp.h"
64 #endif
65
66 #define ok_error(num) ((num)==EIO)
67
68 static int tty_disc = N_TTY;    /* The TTY discipline */
69 static int ppp_disc = N_PPP;    /* The PPP discpline */
70 static int initfdflags = -1;    /* Initial file descriptor flags for fd */
71 static int ppp_fd = -1;         /* fd which is set to PPP discipline */
72 static int sock_fd = -1;        /* socket for doing interface ioctls */
73 static int slave_fd = -1;
74 static int master_fd = -1;
75
76 static int has_proxy_arp       = 0;
77 static int driver_version      = 0;
78 static int driver_modification = 0;
79 static int driver_patch        = 0;
80 static int restore_term        = 0;     /* 1 => we've munged the terminal */
81 static struct termios inittermios;      /* Initial TTY termios */
82
83 static char loop_name[20];
84 static unsigned char inbuf[512]; /* buffer for chars read from loopback */
85
86 static int      if_is_up;       /* Interface has been marked up */
87 static u_int32_t default_route_gateway; /* Gateway for default route added */
88 static u_int32_t proxy_arp_addr;        /* Addr for proxy arp entry added */
89
90 static char *lock_file;
91
92 #define MAX_IFS         100
93
94 #define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
95 #define FLAGS_MASK (IFF_UP          | IFF_BROADCAST | \
96                     IFF_POINTOPOINT | IFF_LOOPBACK  | IFF_NOARP)
97
98 /* Prototypes for procedures local to this file. */
99 static int get_flags (void);
100 static void set_flags (int flags);
101 static int translate_speed (int bps);
102 static int baud_rate_of (int speed);
103 static char *path_to_route (void);
104 static void close_route_table (void);
105 static int open_route_table (void);
106 static int read_route_table (struct rtentry *rt);
107 static int defaultroute_exists (struct rtentry *rt);
108 static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
109                            char *name);
110 static void decode_version (char *buf, int *version, int *mod, int *patch);
111
112 extern u_char   inpacket_buf[]; /* borrowed from main.c */
113
114 /*
115  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
116  * if it exists.
117  */
118
119 #define SET_SA_FAMILY(addr, family)                     \
120     memset ((char *) &(addr), '\0', sizeof(addr));      \
121     addr.sa_family = (family);
122
123 /*
124  * Determine if the PPP connection should still be present.
125  */
126
127 extern int hungup;
128 #define still_ppp() (hungup == 0)
129
130 #ifndef LOCK_PREFIX
131 #define LOCK_PREFIX     "/var/lock/LCK.."
132 #endif
133
134 /********************************************************************
135  *
136  * Functions to read and set the flags value in the device driver
137  */
138
139 static void set_ppp_fd (int new_fd)
140   {    
141     SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", ppp_fd));
142     ppp_fd = new_fd;
143   }
144
145 /********************************************************************
146  *
147  * Functions to read and set the flags value in the device driver
148  */
149
150 static int get_flags (void)
151   {    
152     int flags;
153
154     if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0)
155       {
156         if ( ok_error (errno) )
157           {
158             flags = 0;
159           }
160         else
161           {
162             syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
163             quit();
164           }
165       }
166
167     SYSDEBUG ((LOG_DEBUG, "get flags = %x\n", flags));
168     return flags;
169   }
170
171 /********************************************************************/
172
173 static void set_flags (int flags)
174   {    
175     SYSDEBUG ((LOG_DEBUG, "set flags = %x\n", flags));
176
177     if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
178       {
179         if (! ok_error (errno) )
180           {
181             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS, %x): %m(%d)", flags, errno);
182             quit();
183           }
184       }
185   }
186
187 /********************************************************************
188  *
189  * sys_init - System-dependent initialization.
190  */
191
192 void sys_init(void)
193   {
194     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
195     setlogmask(LOG_UPTO(LOG_INFO));
196     if (debug)
197       {
198         setlogmask(LOG_UPTO(LOG_DEBUG));
199       }
200     
201     /* Get an internet socket for doing socket ioctls. */
202     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
203     if (sock_fd < 0)
204       {
205         if ( ! ok_error ( errno ))
206           {
207             syslog(LOG_ERR, "Couldn't create IP socket: %m(%d)", errno);
208             die(1);
209           }
210       }
211   }
212
213 /********************************************************************
214  *
215  * sys_cleanup - restore any system state we modified before exiting:
216  * mark the interface down, delete default route and/or proxy arp entry.
217  * This should call die() because it's called from die().
218  */
219
220 void sys_cleanup(void)
221   {
222     struct ifreq ifr;
223 /*
224  * Take down the device
225  */
226     if (if_is_up)
227       {
228         sifdown(0);
229       }
230 /*
231  * Delete any routes through the device.
232  */
233     if (default_route_gateway != 0)
234       {
235         cifdefaultroute(0, default_route_gateway);
236       }
237
238     if (has_proxy_arp)
239       {
240         cifproxyarp(0, proxy_arp_addr);
241       }
242   }
243
244 /********************************************************************
245  *
246  * sys_close - Clean up in a child process before execing.
247  */
248 void
249 sys_close(void)
250   {
251     close(sock_fd);
252     sock_fd = -1;
253     closelog();
254   }
255
256 /********************************************************************
257  *
258  * note_debug_level - note a change in the debug level.
259  */
260
261 void note_debug_level (void)
262   {
263     if (debug)
264       {
265         SYSDEBUG ((LOG_INFO, "Debug turned ON, Level %d", debug));
266         setlogmask(LOG_UPTO(LOG_DEBUG));
267       }
268     else
269       {
270         setlogmask(LOG_UPTO(LOG_WARNING));
271       }
272   }
273
274 /********************************************************************
275  *
276  * set_kdebugflag - Define the debugging level for the kernel
277  */
278
279 int set_kdebugflag (int requested_level)
280   {
281     if (ioctl(ppp_fd, PPPIOCSDEBUG, &requested_level) < 0)
282       {
283         if ( ! ok_error (errno) )
284           {
285             syslog (LOG_ERR, "ioctl(PPPIOCSDEBUG): %m");
286           }
287         return (0);
288       }
289     SYSDEBUG ((LOG_INFO, "set kernel debugging level to %d",
290                 requested_level));
291     return (1);
292   }
293
294 /********************************************************************
295  *
296  * establish_ppp - Turn the serial port into a ppp interface.
297  */
298
299 void establish_ppp (int tty_fd)
300   {
301     int x;
302 /*
303  * The current PPP device will be the tty file.
304  */
305     set_ppp_fd (tty_fd);
306 /*
307  * Ensure that the tty device is in exclusive mode.
308  */
309     if (ioctl(tty_fd, TIOCEXCL, 0) < 0)
310       {
311         if ( ! ok_error ( errno ))
312           {
313             syslog (LOG_WARNING, "ioctl(TIOCEXCL): %m");
314           }
315       }
316 /*
317  * Demand mode - prime the old ppp device to relinquish the unit.
318  */
319     if (demand && ioctl(slave_fd, PPPIOCXFERUNIT, 0) < 0)
320       {
321         if ( ! ok_error ( errno ))
322           {
323             syslog(LOG_ERR, "ioctl(transfer ppp unit): %m(%d)", errno);
324             die(1);
325           }
326       }
327 /*
328  * Set the current tty to the PPP discpline
329  */
330     if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
331       {
332         if ( ! ok_error (errno) )
333           {
334             syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
335             die(1);
336           }
337       }
338 /*
339  * Find out which interface we were given.
340  */
341     if (ioctl(ppp_fd, PPPIOCGUNIT, &x) < 0)
342       { 
343         if ( ! ok_error (errno))
344           {
345             syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m(%d)", errno);
346             die(1);
347           }
348       }
349 /*
350  * Check that we got the same unit again.
351  */
352     if (demand)
353       {
354         if (x != ifunit)
355           {
356             syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
357                    ifunit, x);
358             die(1);
359           }
360         ioctl(slave_fd, TIOCSETD, &tty_disc);
361       }
362
363     ifunit = x;
364 /*
365  * Enable debug in the driver if requested.
366  */
367     set_kdebugflag (kdebugflag);
368
369     set_flags (get_flags() & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
370                                SC_RCV_EVNP | SC_RCV_ODDP));
371
372     SYSDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
373             driver_version, driver_modification, driver_patch));
374 /*
375  * Fetch the initial file flags and reset blocking mode on the file.
376  */
377     initfdflags = fcntl(ppp_fd, F_GETFL);
378
379     if (initfdflags == -1 ||
380         fcntl(ppp_fd, F_SETFL, initfdflags | O_NONBLOCK) == -1)
381       {
382         if ( ! ok_error (errno))
383           {
384             syslog(LOG_WARNING,
385                    "Couldn't set device to non-blocking mode: %m");
386           }
387       }
388   }
389
390 /********************************************************************
391  *
392  * disestablish_ppp - Restore the serial port to normal operation.
393  * This shouldn't call die() because it's called from die().
394  */
395
396 void disestablish_ppp(int tty_fd)
397   {
398     int x;
399     char *s;
400 /*
401  * Do nothing if the PPP device is controlled by the loopback device
402  */
403     if (tty_fd != ppp_fd)
404       {
405         return;
406       }
407 /*
408  * Attempt to restore the previous tty settings
409  */
410     if (still_ppp())
411       {
412         set_kdebugflag (0);
413 /*
414  * Restore the previous line discipline
415  */
416         if (ioctl(ppp_fd, TIOCSETD, &tty_disc) < 0)
417           {
418             if ( ! ok_error (errno))
419               {
420                 syslog(LOG_ERR, "ioctl(TIOCSETD, N_TTY): %m");
421               }
422           }
423         
424         if (ioctl(ppp_fd, TIOCNXCL, 0) < 0)
425           {
426             if ( ! ok_error (errno))
427               {
428                 syslog (LOG_WARNING, "ioctl(TIOCNXCL): %m(%d)", errno);
429               }
430           }
431
432         /* Reset non-blocking mode on fd. */
433         if (initfdflags != -1 && fcntl(ppp_fd, F_SETFL, initfdflags) < 0)
434           {
435             if ( ! ok_error (errno))
436               {
437                 syslog (LOG_WARNING,
438                         "Couldn't restore device fd flags: %m");
439               }
440           }
441       }
442     initfdflags = -1;
443   }
444
445 /********************************************************************
446  *
447  * clean_check - Fetch the flags for the device and generate
448  * appropriate error messages.
449  */
450 void clean_check(void)
451   {
452     int x;
453     char *s;
454
455     if (still_ppp())
456       {
457         if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0)
458           {
459             s = NULL;
460             switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP))
461               {
462               case SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP:
463                 s = "nothing was received";
464                 break;
465                 
466               case SC_RCV_B7_0:
467               case SC_RCV_B7_0 | SC_RCV_EVNP:
468               case SC_RCV_B7_0 | SC_RCV_ODDP:
469               case SC_RCV_B7_0 | SC_RCV_ODDP | SC_RCV_EVNP:
470                 s = "all had bit 7 set to 1";
471                 break;
472                 
473               case SC_RCV_B7_1:
474               case SC_RCV_B7_1 | SC_RCV_EVNP:
475               case SC_RCV_B7_1 | SC_RCV_ODDP:
476               case SC_RCV_B7_1 | SC_RCV_ODDP | SC_RCV_EVNP:
477                 s = "all had bit 7 set to 0";
478                 break;
479                 
480               case SC_RCV_EVNP:
481                 s = "all had odd parity";
482                 break;
483                 
484               case SC_RCV_ODDP:
485                 s = "all had even parity";
486                 break;
487               }
488             
489             if (s != NULL)
490               {
491                 syslog(LOG_WARNING, "Receive serial link is not"
492                        " 8-bit clean:");
493                 syslog(LOG_WARNING, "Problem: %s", s);
494               }
495           }
496       }
497   }
498         
499
500 /*
501  * List of valid speeds.
502  */
503
504 struct speed {
505     int speed_int, speed_val;
506 } speeds[] = {
507 #ifdef B50
508     { 50, B50 },
509 #endif
510 #ifdef B75
511     { 75, B75 },
512 #endif
513 #ifdef B110
514     { 110, B110 },
515 #endif
516 #ifdef B134
517     { 134, B134 },
518 #endif
519 #ifdef B150
520     { 150, B150 },
521 #endif
522 #ifdef B200
523     { 200, B200 },
524 #endif
525 #ifdef B300
526     { 300, B300 },
527 #endif
528 #ifdef B600
529     { 600, B600 },
530 #endif
531 #ifdef B1200
532     { 1200, B1200 },
533 #endif
534 #ifdef B1800
535     { 1800, B1800 },
536 #endif
537 #ifdef B2000
538     { 2000, B2000 },
539 #endif
540 #ifdef B2400
541     { 2400, B2400 },
542 #endif
543 #ifdef B3600
544     { 3600, B3600 },
545 #endif
546 #ifdef B4800
547     { 4800, B4800 },
548 #endif
549 #ifdef B7200
550     { 7200, B7200 },
551 #endif
552 #ifdef B9600
553     { 9600, B9600 },
554 #endif
555 #ifdef B19200
556     { 19200, B19200 },
557 #endif
558 #ifdef B38400
559     { 38400, B38400 },
560 #endif
561 #ifdef B57600
562     { 57600, B57600 },
563 #endif
564 #ifdef B115200
565     { 115200, B115200 },
566 #endif
567 #ifdef EXTA
568     { 19200, EXTA },
569 #endif
570 #ifdef EXTB
571     { 38400, EXTB },
572 #endif
573     { 0, 0 }
574 };
575
576 /********************************************************************
577  *
578  * Translate from bits/second to a speed_t.
579  */
580
581 static int translate_speed (int bps)
582   {
583     struct speed *speedp;
584
585     if (bps != 0)
586       {
587         for (speedp = speeds; speedp->speed_int; speedp++)
588           {
589             if (bps == speedp->speed_int)
590               {
591                 return speedp->speed_val;
592               }
593           }
594         syslog(LOG_WARNING, "speed %d not supported", bps);
595       }
596     return 0;
597   }
598
599 /********************************************************************
600  *
601  * Translate from a speed_t to bits/second.
602  */
603
604 static int baud_rate_of (int speed)
605   {
606     struct speed *speedp;
607     
608     if (speed != 0)
609       {
610         for (speedp = speeds; speedp->speed_int; speedp++)
611           {
612             if (speed == speedp->speed_val)
613               {
614                 return speedp->speed_int;
615               }
616           }
617       }
618     return 0;
619   }
620
621 /********************************************************************
622  *
623  * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
624  * at the requested speed, etc.  If `local' is true, set CLOCAL
625  * regardless of whether the modem option was specified.
626  */
627
628 void set_up_tty (int tty_fd, int local)
629   {
630     int speed, x;
631     struct termios tios;
632     
633     if (tcgetattr(tty_fd, &tios) < 0)
634       {
635         syslog(LOG_ERR, "tcgetattr: %m(%d)", errno);
636         die(1);
637       }
638     
639     if (!restore_term)
640       {
641         inittermios = tios;
642       }
643     
644     tios.c_cflag     &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
645     tios.c_cflag     |= CS8 | CREAD | HUPCL;
646
647     tios.c_iflag      = IGNBRK | IGNPAR;
648     tios.c_oflag      = 0;
649     tios.c_lflag      = 0;
650     tios.c_cc[VMIN]   = 1;
651     tios.c_cc[VTIME]  = 0;
652     
653     if (local || !modem)
654       {
655         tios.c_cflag ^= (CLOCAL | HUPCL);
656       }
657
658     switch (crtscts)
659       {
660     case 1:
661         tios.c_cflag |= CRTSCTS;
662         break;
663
664     case -2:
665         tios.c_iflag     |= IXON | IXOFF;
666         tios.c_cc[VSTOP]  = 0x13;       /* DC3 = XOFF = ^S */
667         tios.c_cc[VSTART] = 0x11;       /* DC1 = XON  = ^Q */
668         break;
669
670     case -1:
671         tios.c_cflag &= ~CRTSCTS;
672         break;
673
674     default:
675         break;
676       }
677     
678     speed = translate_speed(inspeed);
679     if (speed)
680       {
681         cfsetospeed (&tios, speed);
682         cfsetispeed (&tios, speed);
683       }
684 /*
685  * We can't proceed if the serial port speed is B0,
686  * since that implies that the serial port is disabled.
687  */
688     else
689       {
690         speed = cfgetospeed(&tios);
691         if (speed == B0)
692           {
693             syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
694                    devnam);
695             die (1);
696           }
697       }
698
699     if (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0)
700       {
701         syslog(LOG_ERR, "tcsetattr: %m");
702         die(1);
703       }
704     
705     baud_rate    = baud_rate_of(speed);
706     restore_term = TRUE;
707   }
708
709 /********************************************************************
710  *
711  * setdtr - control the DTR line on the serial port.
712  * This is called from die(), so it shouldn't call die().
713  */
714
715 void setdtr (int tty_fd, int on)
716   {
717     int modembits = TIOCM_DTR;
718
719     ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
720   }
721
722 /********************************************************************
723  *
724  * restore_tty - restore the terminal to the saved settings.
725  */
726
727 void restore_tty (int tty_fd)
728   {
729     if (restore_term)
730       {
731         restore_term = 0;
732 /*
733  * Turn off echoing, because otherwise we can get into
734  * a loop with the tty and the modem echoing to each other.
735  * We presume we are the sole user of this tty device, so
736  * when we close it, it will revert to its defaults anyway.
737  */
738         if (!default_device)
739           {
740             inittermios.c_lflag &= ~(ECHO | ECHONL);
741           }
742         
743         if (tcsetattr(tty_fd, TCSAFLUSH, &inittermios) < 0)
744           {
745             if (! ok_error (errno))
746               {
747                 syslog(LOG_WARNING, "tcsetattr: %m");
748               }
749           }
750       }
751   }
752
753 /********************************************************************
754  *
755  * output - Output PPP packet.
756  */
757
758 void output (int unit, unsigned char *p, int len)
759   {
760     if (debug)
761       {
762         log_packet(p, len, "sent ");
763       }
764     
765     if (write(ppp_fd, p, len) < 0)
766       {
767         if (errno == EWOULDBLOCK || errno == ENOBUFS
768             || errno == ENXIO || errno == EIO)
769           {
770             syslog(LOG_WARNING, "write: warning: %m(%d)", errno);
771           } 
772         else
773           {
774             syslog(LOG_ERR, "write: %m(%d)", errno);
775             die(1);
776           }
777       }
778   }
779
780 /********************************************************************
781  *
782  * wait_input - wait until there is data available on ppp_fd,
783  * for the length of time specified by *timo (indefinite
784  * if timo is NULL).
785  */
786
787 void wait_input (struct timeval *timo)
788   {
789     fd_set ready;
790     int n;
791     
792     FD_ZERO(&ready);
793     FD_SET(ppp_fd, &ready);
794
795     n = select(ppp_fd + 1, &ready, NULL, &ready, timo);
796     if (n < 0 && errno != EINTR)
797       {
798         syslog(LOG_ERR, "select: %m(%d)", errno);
799         die(1);
800       }
801   }
802
803 /********************************************************************
804  *
805  * wait_loop_output - wait until there is data available on the
806  * loopback, for the length of time specified by *timo (indefinite
807  * if timo is NULL).
808  */
809 void wait_loop_output(timo)
810     struct timeval *timo;
811   {
812     fd_set ready;
813     int n;
814
815     FD_ZERO(&ready);
816     FD_SET(master_fd, &ready);
817     n = select(master_fd + 1, &ready, NULL, &ready, timo);
818     if (n < 0 && errno != EINTR)
819       {
820         syslog(LOG_ERR, "select: %m(%d)", errno);
821         die(1);
822       }
823   }
824
825 /********************************************************************
826  *
827  * wait_time - wait for a given length of time or until a
828  * signal is received.
829  */
830
831 void wait_time(timo)
832     struct timeval *timo;
833 {
834     int n;
835
836     n = select(0, NULL, NULL, NULL, timo);
837     if (n < 0 && errno != EINTR) {
838         syslog(LOG_ERR, "select: %m(%d)", errno);
839         die(1);
840     }
841 }
842
843 /********************************************************************
844  *
845  * read_packet - get a PPP packet from the serial device.
846  */
847
848 int read_packet (unsigned char *buf)
849   {
850     int len;
851   
852     len = read(ppp_fd, buf, PPP_MTU + PPP_HDRLEN);
853     if (len < 0)
854       {
855         if (errno == EWOULDBLOCK)
856           {
857             return -1;
858           }
859         syslog(LOG_ERR, "read: %m(%d)", errno);
860         die(1);
861       }
862     return len;
863   }
864
865 /********************************************************************
866  *
867  * get_loop_output - get outgoing packets from the ppp device,
868  * and detect when we want to bring the real link up.
869  * Return value is 1 if we need to bring up the link, 0 otherwise.
870  */
871 int
872 get_loop_output(void)
873   {
874     int rv = 0;
875     int n  = read(master_fd, inbuf, sizeof(inbuf));
876
877     while (n > 0)
878       {
879         if (loop_chars(inbuf, n))
880           {
881             rv = 1;
882           }
883         n = read(master_fd, inbuf, sizeof(inbuf));
884       }
885
886     if (n == 0)
887       {
888         syslog(LOG_ERR, "eof on loopback");
889         die(1);
890       }
891
892     if (errno != EWOULDBLOCK)
893       {
894         syslog(LOG_ERR, "read from loopback: %m(%d)", errno);
895         die(1);
896       }
897     
898     return rv;
899   }
900
901 /********************************************************************
902  *
903  * ppp_send_config - configure the transmit characteristics of
904  * the ppp interface.
905  */
906
907 void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
908   {
909     u_int x;
910     struct ifreq ifr;
911   
912     SYSDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
913 /*
914  * Ensure that the link is still up.
915  */
916     if (still_ppp())
917       {
918 /*
919  * Set the MTU and other parameters for the ppp device
920  */
921         memset (&ifr, '\0', sizeof (ifr));
922         strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
923         ifr.ifr_mtu = mtu;
924         
925         if (ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
926           {
927             syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m(%d)", errno);
928             quit();
929           }
930         
931         SYSDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
932         if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
933           {
934             syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m(%d)", errno);
935             quit();
936           }
937     
938         x = get_flags();
939         x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
940         x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
941         set_flags(x);
942       }
943   }
944
945 /********************************************************************
946  *
947  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
948  */
949
950 void ppp_set_xaccm (int unit, ext_accm accm)
951   {
952     SYSDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
953                 accm[0], accm[1], accm[2], accm[3]));
954
955     if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
956       {
957         if ( ! ok_error (errno))
958           {
959             syslog(LOG_WARNING, "ioctl(set extended ACCM): %m(%d)", errno);
960           }
961       }
962   }
963
964 /********************************************************************
965  *
966  * ppp_recv_config - configure the receive-side characteristics of
967  * the ppp interface.
968  */
969
970 void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
971   {
972     u_int x;
973
974     SYSDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
975 /*
976  * If we were called because the link has gone down then there is nothing
977  * which may be done. Just return without incident.
978  */
979     if (!still_ppp())
980       {
981         return;
982       }
983 /*
984  * Set the receiver parameters
985  */
986     if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
987       {
988         if ( ! ok_error (errno))
989           {
990             syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m(%d)", errno);
991           }
992       }
993
994     SYSDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
995     if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
996       {
997         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m(%d)", errno);
998         quit();
999       }
1000
1001     x = get_flags();
1002     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
1003     set_flags (x);
1004   }
1005
1006 /********************************************************************
1007  *
1008  * ccp_test - ask kernel whether a given compression method
1009  * is acceptable for use.
1010  */
1011
1012 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
1013   {
1014     struct ppp_option_data data;
1015
1016     memset (&data, '\0', sizeof (data));
1017     data.ptr      = opt_ptr;
1018     data.length   = opt_len;
1019     data.transmit = for_transmit;
1020
1021     if (ioctl(ppp_fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
1022       {
1023         return 1;
1024       }
1025
1026     return (errno == ENOBUFS)? 0: -1;
1027   }
1028
1029 /********************************************************************
1030  *
1031  * ccp_flags_set - inform kernel about the current state of CCP.
1032  */
1033
1034 void ccp_flags_set (int unit, int isopen, int isup)
1035   {
1036     if (still_ppp())
1037       {
1038         int x = get_flags();
1039         x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
1040         x = isup?   x | SC_CCP_UP   : x &~ SC_CCP_UP;
1041         set_flags (x);
1042       }
1043   }
1044
1045 /********************************************************************
1046  *
1047  * get_idle_time - return how long the link has been idle.
1048  */
1049 int
1050 get_idle_time(u, ip)
1051     int u;
1052     struct ppp_idle *ip;
1053 {
1054     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
1055
1056
1057 /********************************************************************
1058  *
1059  * ccp_fatal_error - returns 1 if decompression was disabled as a
1060  * result of an error detected after decompression of a packet,
1061  * 0 otherwise.  This is necessary because of patent nonsense.
1062  */
1063
1064 int ccp_fatal_error (int unit)
1065   {
1066     int x = get_flags();
1067
1068     return x & SC_DC_FERROR;
1069   }
1070
1071 /*
1072  * path_to_route - determine the path to the proc file system data
1073  */
1074
1075 FILE *route_fd = (FILE *) 0;
1076 static char route_buffer [512];
1077
1078 static char *path_to_route (void);
1079 static int open_route_table (void);
1080 static void close_route_table (void);
1081 static int read_route_table (struct rtentry *rt);
1082
1083 /********************************************************************
1084  *
1085  * path_to_procfs - find the path to the proc file system mount point
1086  */
1087
1088 static int path_to_procfs (void)
1089   {
1090     struct mntent *mntent;
1091     FILE *fp;
1092
1093     fp = fopen (MOUNTED, "r");
1094     if (fp != 0)
1095       {
1096         mntent = getmntent (fp);
1097         while (mntent != (struct mntent *) 0)
1098           {
1099             if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) != 0)
1100               {
1101                 if (strcmp (mntent->mnt_type, "proc") == 0)
1102                   {
1103                     strncpy (route_buffer, mntent->mnt_dir,
1104                              sizeof (route_buffer)-10);
1105                     route_buffer [sizeof (route_buffer)-10] = '\0';
1106                     fclose (fp);
1107                     return 1;
1108                   }
1109               }
1110             mntent = getmntent (fp);
1111           }
1112         fclose (fp);
1113       }
1114     return 0;
1115   }
1116
1117 /********************************************************************
1118  *
1119  * path_to_route - find the path to the route tables in the proc file system
1120  */
1121
1122 static char *path_to_route (void)
1123   {
1124     if (! path_to_procfs())
1125       {
1126         syslog (LOG_ERR, "proc file system not mounted");
1127         return 0;
1128       }
1129     strcat (route_buffer, "/net/route");
1130     return (route_buffer);
1131   }
1132
1133 /********************************************************************
1134  *
1135  * close_route_table - close the interface to the route table
1136  */
1137
1138 static void close_route_table (void)
1139   {
1140     if (route_fd != (FILE *) 0)
1141       {
1142         fclose (route_fd);
1143         route_fd = (FILE *) 0;
1144       }
1145   }
1146
1147 /********************************************************************
1148  *
1149  * open_route_table - open the interface to the route table
1150  */
1151
1152 static int open_route_table (void)
1153   {
1154     char *path;
1155
1156     close_route_table();
1157
1158     path = path_to_route();
1159     if (path == NULL)
1160       {
1161         return 0;
1162       }
1163
1164     route_fd = fopen (path, "r");
1165     if (route_fd == (FILE *) 0)
1166       {
1167         syslog (LOG_ERR, "can not open %s: %m(%d)", path, errno);
1168         return 0;
1169       }
1170     return 1;
1171   }
1172
1173 /********************************************************************
1174  *
1175  * read_route_table - read the next entry from the route table
1176  */
1177
1178 static int read_route_table (struct rtentry *rt)
1179   {
1180     static char delims[] = " \t\n";
1181     char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
1182         
1183     memset (rt, '\0', sizeof (struct rtentry));
1184
1185     for (;;)
1186       {
1187         if (fgets (route_buffer, sizeof (route_buffer), route_fd) ==
1188             (char *) 0)
1189           {
1190             return 0;
1191           }
1192
1193         dev_ptr  = strtok (route_buffer, delims); /* interface name */
1194         dst_ptr  = strtok (NULL,         delims); /* destination address */
1195         gw_ptr   = strtok (NULL,         delims); /* gateway */
1196         flag_ptr = strtok (NULL,         delims); /* flags */
1197     
1198         if (flag_ptr == (char *) 0) /* assume that we failed, somewhere. */
1199           {
1200             return 0;
1201           }
1202         
1203         /* Discard that stupid header line which should never
1204          * have been there in the first place !! */
1205         if (isxdigit (*dst_ptr) && isxdigit (*gw_ptr) && isxdigit (*flag_ptr))
1206           {
1207             break;
1208           }
1209       }
1210
1211     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
1212       strtoul (dst_ptr, NULL, 16);
1213
1214     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
1215       strtoul (gw_ptr, NULL, 16);
1216
1217     rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
1218     rt->rt_dev   = dev_ptr;
1219
1220     return 1;
1221   }
1222
1223 /********************************************************************
1224  *
1225  * defaultroute_exists - determine if there is a default route
1226  */
1227
1228 static int defaultroute_exists (struct rtentry *rt)
1229   {
1230     int    result = 0;
1231
1232     if (!open_route_table())
1233       {
1234         return 0;
1235       }
1236
1237     while (read_route_table(rt) != 0)
1238       {
1239         if ((rt->rt_flags & RTF_UP) == 0)
1240           {
1241             continue;
1242           }
1243
1244         if (((struct sockaddr_in *) (&rt->rt_dst))->sin_addr.s_addr == 0L)
1245           {
1246             result = 1;
1247             break;
1248           }
1249       }
1250
1251     close_route_table();
1252     return result;
1253   }
1254
1255 /********************************************************************
1256  *
1257  * sifdefaultroute - assign a default route through the address given.
1258  */
1259
1260 int sifdefaultroute (int unit, u_int32_t gateway)
1261   {
1262     struct rtentry rt;
1263
1264     if (defaultroute_exists(&rt))
1265       {
1266         u_int32_t old_gateway = ((struct sockaddr_in *) (&rt.rt_gateway))->
1267                                 sin_addr.s_addr;
1268
1269         if (old_gateway != gateway)
1270           {
1271             syslog (LOG_ERR,
1272                     "ppp not replacing existing default route to %s[%s]",
1273                     rt.rt_dev,
1274                     inet_ntoa (old_gateway));
1275           }
1276         return 0;
1277       }
1278
1279     memset (&rt, '\0', sizeof (rt));
1280     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1281     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1282     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1283     
1284     rt.rt_flags = RTF_UP | RTF_GATEWAY;
1285     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0)
1286       {
1287         if ( ! ok_error ( errno ))
1288           {
1289             syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m(%d)", errno);
1290           }
1291         return 0;
1292       }
1293
1294     default_route_gateway = gateway;
1295     return 1;
1296   }
1297
1298 /********************************************************************
1299  *
1300  * cifdefaultroute - delete a default route through the address given.
1301  */
1302
1303 int cifdefaultroute (int unit, u_int32_t gateway)
1304   {
1305     struct rtentry rt;
1306
1307     default_route_gateway = 0;
1308
1309     memset (&rt, '\0', sizeof (rt));
1310     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
1311     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1312     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1313     
1314     rt.rt_flags = RTF_UP | RTF_GATEWAY;
1315     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH)
1316       {
1317         if (still_ppp())
1318           {
1319             if ( ! ok_error ( errno ))
1320               {
1321                 syslog (LOG_ERR,
1322                         "default route ioctl(SIOCDELRT): %m(%d)", errno);
1323               }
1324             return 0;
1325           }
1326       }
1327
1328     return 1;
1329   }
1330
1331 /********************************************************************
1332  *
1333  * sifproxyarp - Make a proxy ARP entry for the peer.
1334  */
1335
1336 int sifproxyarp (int unit, u_int32_t his_adr)
1337   {
1338     struct arpreq arpreq;
1339
1340     if (has_proxy_arp == 0)
1341       {
1342         memset (&arpreq, '\0', sizeof(arpreq));
1343     
1344         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1345         ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1346         arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1347 /*
1348  * Get the hardware address of an interface on the same subnet
1349  * as our local address.
1350  */
1351         if (!get_ether_addr(his_adr, &arpreq.arp_ha, arpreq.arp_dev))
1352           {
1353             syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1354             return 0;
1355           }
1356         
1357         if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0)
1358           {
1359             if ( ! ok_error ( errno ))
1360               {
1361                 syslog(LOG_ERR, "ioctl(SIOCSARP): %m(%d)", errno);
1362               }
1363             return 0;
1364           }
1365       }
1366
1367     proxy_arp_addr = his_adr;
1368     has_proxy_arp = 1;
1369     return 1;
1370   }
1371
1372 /********************************************************************
1373  *
1374  * cifproxyarp - Delete the proxy ARP entry for the peer.
1375  */
1376
1377 int cifproxyarp (int unit, u_int32_t his_adr)
1378   {
1379     struct arpreq arpreq;
1380
1381     if (has_proxy_arp == 1)
1382       {
1383         memset (&arpreq, '\0', sizeof(arpreq));
1384         SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1385     
1386         ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1387         if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0)
1388           {
1389             if ( ! ok_error ( errno ))
1390               {
1391                 syslog(LOG_WARNING, "ioctl(SIOCDARP): %m(%d)", errno);
1392               }
1393             return 0;
1394           }
1395       }
1396     has_proxy_arp = 0;
1397     return 1;
1398   }
1399      
1400 /********************************************************************
1401  *
1402  * get_ether_addr - get the hardware address of an interface on the
1403  * the same subnet as ipaddr.
1404  */
1405
1406 static int get_ether_addr (u_int32_t ipaddr,
1407                            struct sockaddr *hwaddr,
1408                            char *name)
1409   {
1410     struct ifreq *ifr, *ifend, *ifp;
1411     int i;
1412     u_int32_t ina, mask;
1413     struct sockaddr_dl *dla;
1414     struct ifreq ifreq;
1415     struct ifconf ifc;
1416     struct ifreq ifs[MAX_IFS];
1417     
1418     ifc.ifc_len = sizeof(ifs);
1419     ifc.ifc_req = ifs;
1420     if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0)
1421       {
1422         if ( ! ok_error ( errno ))
1423           {
1424             syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m(%d)", errno);
1425           }
1426         return 0;
1427       }
1428
1429     SYSDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
1430                 ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
1431 /*
1432  * Scan through looking for an interface with an Internet
1433  * address on the same subnet as `ipaddr'.
1434  */
1435     ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1436     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1437       {
1438         if (ifr->ifr_addr.sa_family == AF_INET)
1439           {
1440             ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1441             strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1442             SYSDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
1443                         ifreq.ifr_name));
1444 /*
1445  * Check that the interface is up, and not point-to-point
1446  * nor loopback.
1447  */
1448             if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1449               {
1450                 continue;
1451               }
1452
1453             if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1454               {
1455                 continue;
1456               }
1457 /*
1458  * Get its netmask and check that it's on the right subnet.
1459  */
1460             if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1461               {
1462                 continue;
1463               }
1464
1465             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1466             SYSDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
1467                         ip_ntoa(ina), ntohl(mask)));
1468
1469             if (((ipaddr ^ ina) & mask) != 0)
1470               {
1471                 continue;
1472               }
1473             break;
1474           }
1475       }
1476     
1477     if (ifr >= ifend)
1478       {
1479         return 0;
1480       }
1481
1482     memcpy (name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
1483     syslog(LOG_INFO, "found interface %s for proxy arp", name);
1484 /*
1485  * Now get the hardware address.
1486  */
1487     memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
1488     if (ioctl (sock_fd, SIOCGIFHWADDR, &ifreq) < 0)
1489       {
1490         syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m(%d)", ifreq.ifr_name, errno);
1491         return 0;
1492       }
1493
1494     memcpy (hwaddr,
1495             &ifreq.ifr_hwaddr,
1496             sizeof (struct sockaddr));
1497
1498     SYSDEBUG ((LOG_DEBUG,
1499            "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1500                 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1501                 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1502                 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1503                 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1504                 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1505                 (int) ((unsigned char *) &hwaddr->sa_data)[5],
1506                 (int) ((unsigned char *) &hwaddr->sa_data)[6],
1507                 (int) ((unsigned char *) &hwaddr->sa_data)[7]));
1508     return 1;
1509   }
1510
1511 /********************************************************************
1512  *
1513  * Return user specified netmask, modified by any mask we might determine
1514  * for address `addr' (in network byte order).
1515  * Here we scan through the system's list of interfaces, looking for
1516  * any non-point-to-point interfaces which might appear to be on the same
1517  * network as `addr'.  If we find any, we OR in their netmask to the
1518  * user-specified netmask.
1519  */
1520
1521 u_int32_t GetMask (u_int32_t addr)
1522   {
1523     u_int32_t mask, nmask, ina;
1524     struct ifreq *ifr, *ifend, ifreq;
1525     struct ifconf ifc;
1526     struct ifreq ifs[MAX_IFS];
1527
1528     addr = ntohl(addr);
1529     
1530     if (IN_CLASSA(addr))        /* determine network mask for address class */
1531       {
1532         nmask = IN_CLASSA_NET;
1533       }
1534     else
1535       {
1536         if (IN_CLASSB(addr))
1537           {
1538             nmask = IN_CLASSB_NET;
1539           }
1540         else
1541           {
1542             nmask = IN_CLASSC_NET;
1543           }
1544       }
1545     
1546     /* class D nets are disallowed by bad_ip_adrs */
1547     mask = netmask | htonl(nmask);
1548 /*
1549  * Scan through the system's network interfaces.
1550  */
1551     ifc.ifc_len = sizeof(ifs);
1552     ifc.ifc_req = ifs;
1553     if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0)
1554       {
1555         if ( ! ok_error ( errno ))
1556           {
1557             syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m(%d)", errno);
1558           }
1559         return mask;
1560       }
1561     
1562     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1563     for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1564       {
1565 /*
1566  * Check the interface's internet address.
1567  */
1568         if (ifr->ifr_addr.sa_family != AF_INET)
1569           {
1570             continue;
1571           }
1572         ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1573         if (((ntohl(ina) ^ addr) & nmask) != 0)
1574           {
1575             continue;
1576           }
1577 /*
1578  * Check that the interface is up, and not point-to-point nor loopback.
1579  */
1580         strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1581         if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
1582           {
1583             continue;
1584           }
1585         
1586         if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1587           {
1588             continue;
1589           }
1590 /*
1591  * Get its netmask and OR it into our mask.
1592  */
1593         if (ioctl(sock_fd, SIOCGIFNETMASK, &ifreq) < 0)
1594           {
1595             continue;
1596           }
1597         mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1598         break;
1599       }
1600     return mask;
1601   }
1602
1603 /********************************************************************
1604  *
1605  * Internal routine to decode the version.modification.patch level
1606  */
1607
1608 static void decode_version (char *buf, int *version,
1609                             int *modification, int *patch)
1610   {
1611     *version      = (int) strtoul (buf, &buf, 10);
1612     *modification = 0;
1613     *patch        = 0;
1614     
1615     if (*buf == '.')
1616       {
1617         ++buf;
1618         *modification = (int) strtoul (buf, &buf, 10);
1619         if (*buf == '.')
1620           {
1621             ++buf;
1622             *patch = (int) strtoul (buf, &buf, 10);
1623           }
1624       }
1625     
1626     if (*buf != '\0')
1627       {
1628         *version      =
1629         *modification =
1630         *patch        = 0;
1631       }
1632   }
1633
1634 /********************************************************************
1635  *
1636  * Procedure to determine if the PPP line dicipline is registered.
1637  */
1638
1639 int
1640 ppp_registered(void)
1641   {
1642     int local_fd;
1643     int init_disc = -1;
1644     int initfdflags;
1645
1646     local_fd = open(devnam, O_NONBLOCK | O_RDWR, 0);
1647     if (local_fd < 0)
1648       {
1649         syslog(LOG_ERR, "Failed to open %s: %m(%d)", devnam, errno);
1650         return 0;
1651       }
1652
1653     initfdflags = fcntl(local_fd, F_GETFL);
1654     if (initfdflags == -1)
1655       {
1656         syslog(LOG_ERR, "Couldn't get device fd flags: %m(%d)", errno);
1657         close (local_fd);
1658         return 0;
1659       }
1660
1661     initfdflags &= ~O_NONBLOCK;
1662     fcntl(local_fd, F_SETFL, initfdflags);
1663 /*
1664  * Read the initial line dicipline and try to put the device into the
1665  * PPP dicipline.
1666  */
1667     if (ioctl(local_fd, TIOCGETD, &init_disc) < 0)
1668       {
1669         syslog(LOG_ERR, "ioctl(TIOCGETD): %m(%d)", errno);
1670         close (local_fd);
1671         return 0;
1672       }
1673     
1674     if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0)
1675       {
1676         syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
1677         close (local_fd);
1678         return 0;
1679       }
1680     
1681     if (ioctl(local_fd, TIOCSETD, &init_disc) < 0)
1682       {
1683         syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
1684         close (local_fd);
1685         return 0;
1686       }
1687     
1688     close (local_fd);
1689     return 1;
1690   }
1691
1692 /********************************************************************
1693  *
1694  * ppp_available - check whether the system has any ppp interfaces
1695  * (in fact we check whether we can do an ioctl on ppp0).
1696  */
1697
1698 int ppp_available(void)
1699   {
1700     int s, ok;
1701     struct ifreq ifr;
1702     int    size;
1703     int    my_version, my_modification, my_patch;
1704     extern char *no_ppp_msg;
1705 /*
1706  * Open a socket for doing the ioctl operations.
1707  */    
1708     s = socket(AF_INET, SOCK_DGRAM, 0);
1709     if (s < 0)
1710       {
1711         return 0;
1712       }
1713     
1714     strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1715     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1716 /*
1717  * If the device did not exist then attempt to create one by putting the
1718  * current tty into the PPP discipline. If this works then obtain the
1719  * flags for the device again.
1720  */
1721     if (!ok)
1722       {
1723         if (ppp_registered())
1724           {
1725             strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1726             ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1727           }
1728       }
1729 /*
1730  * Ensure that the hardware address is for PPP and not something else
1731  */
1732     if (ok)
1733       {
1734         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
1735       }
1736
1737     if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
1738       {
1739         ok = 0;
1740       }
1741
1742     if (!ok)
1743       {
1744         no_ppp_msg = 
1745           "This system lacks kernel support for PPP. To include PPP support\n"
1746           "in the kernel, please follow the steps detailed in the "
1747           "README.linux\nfile in the ppp-2.3 distribution.\n";
1748       }
1749 /*
1750  *  This is the PPP device. Validate the version of the driver at this
1751  *  point to ensure that this program will work with the driver.
1752  */
1753     else
1754       {
1755         char   abBuffer [1024];
1756
1757         ifr.ifr_data = abBuffer;
1758         size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
1759         ok   = size >= 0;
1760
1761         if (ok)
1762           {
1763             decode_version (abBuffer,
1764                             &driver_version,
1765                             &driver_modification,
1766                             &driver_patch);
1767           }
1768     
1769         if (!ok)
1770           {
1771             driver_version      =
1772             driver_modification =
1773             driver_patch        = 0;
1774           }
1775 /*
1776  * Validate the version of the driver against the version that we used.
1777  */
1778         decode_version (PPP_VERSION,
1779                         &my_version,
1780                         &my_modification,
1781                         &my_patch);
1782
1783         /* The version numbers must match */
1784         if (driver_version != my_version)
1785           {
1786             ok = 0;
1787           }
1788       
1789         /* The modification levels must be legal */
1790         if (driver_modification < my_modification)
1791           {
1792             ok = 0;
1793           }
1794
1795         close (s);
1796         if (!ok)
1797           {
1798             sprintf (route_buffer,
1799                      "Sorry - PPP driver version %d.%d.%d is out of date\n",
1800                      driver_version, driver_modification, driver_patch);
1801
1802             no_ppp_msg = route_buffer;
1803           }
1804       }
1805     return ok;
1806   }
1807
1808 /********************************************************************
1809  *
1810  * Update the wtmp file with the appropriate user name and tty device.
1811  */
1812
1813 int logwtmp (char *line, char *name, char *host)
1814   {
1815     int    wtmp;
1816     struct utmp ut, *utp;
1817     pid_t  mypid = getpid();
1818 /*
1819  * Update the signon database for users.
1820  * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
1821  */
1822     utmpname(_PATH_UTMP);
1823     setutent();
1824     while ((utp = getutent()) && (utp->ut_pid != mypid))
1825         /* nothing */;
1826
1827     /* Is this call really necessary? There is another one after the 'put' */
1828     endutent();
1829     
1830     if (utp)
1831       {
1832         memcpy(&ut, utp, sizeof(ut));
1833       }
1834     else
1835       {
1836         /* some gettys/telnetds don't initialize utmp... */
1837         memset(&ut, 0, sizeof(ut));
1838       }
1839
1840     if (ut.ut_id[0] == 0)
1841       {
1842         strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
1843       }
1844         
1845     strncpy(ut.ut_user, name, sizeof(ut.ut_user));
1846     strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1847
1848     time(&ut.ut_time);
1849
1850     ut.ut_type = USER_PROCESS;
1851     ut.ut_pid  = mypid;
1852
1853     /* Insert the host name if one is supplied */
1854     if (*host)
1855       {
1856         strncpy (ut.ut_host, host, sizeof(ut.ut_host));
1857       }
1858
1859     /* Insert the IP address of the remote system if IP is enabled */
1860     if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
1861       {
1862         memcpy  (&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
1863                  sizeof(ut.ut_addr));
1864       }
1865         
1866     /* CL: Makes sure that the logout works */
1867     if (*host == 0 && *name==0)
1868       {
1869         ut.ut_host[0]=0;
1870       }
1871
1872     pututline(&ut);
1873     endutent();
1874 /*
1875  * Update the wtmp file.
1876  */
1877     wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
1878     if (wtmp >= 0)
1879       {
1880         flock(wtmp, LOCK_EX);
1881
1882         /* we really should check for error on the write for a full disk! */
1883         write (wtmp, (char *)&ut, sizeof(ut));
1884         close (wtmp);
1885
1886         flock(wtmp, LOCK_UN);
1887       }
1888   }
1889
1890 /********************************************************************
1891  * Code for locking/unlocking the serial device.
1892  * This code is derived from chat.c.
1893  */
1894
1895 /*
1896  * lock - create a lock file for the named device
1897  */
1898
1899 int lock (char *dev)
1900   {
1901     char hdb_lock_buffer[12];
1902     int fd, n;
1903     int pid = getpid();
1904     char *p;
1905
1906     p = strrchr(dev, '/');
1907     if (p != NULL)
1908       {
1909         dev = ++p;
1910       }
1911
1912     lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1913     if (lock_file == NULL)
1914       {
1915         novm("lock file name");
1916       }
1917
1918     strcpy (lock_file, LOCK_PREFIX);
1919     strcat (lock_file, dev);
1920 /*
1921  * Attempt to create the lock file at this point.
1922  */
1923     while (1)
1924       {
1925         fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644);
1926         if (fd >= 0)
1927           {
1928             pid = getpid();
1929 #ifndef PID_BINARY
1930             sprintf (hdb_lock_buffer, "%010d\n", pid);
1931             write (fd, hdb_lock_buffer, 11);
1932 #else
1933             write(fd, &pid, sizeof (pid));
1934 #endif
1935             close(fd);
1936             return 0;
1937           }
1938 /*
1939  * If the file exists then check to see if the pid is stale
1940  */
1941         if (errno == EEXIST)
1942           {
1943             fd = open(lock_file, O_RDONLY, 0);
1944             if (fd < 0)
1945               {
1946                 if (errno == ENOENT) /* This is just a timing problem. */
1947                   {
1948                     continue;
1949                   }
1950                 break;
1951               }
1952
1953             /* Read the lock file to find out who has the device locked */
1954             n = read (fd, hdb_lock_buffer, 11);
1955             close (fd);
1956             if (n < 0)
1957               {
1958                 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1959                 break;
1960               }
1961
1962             /* See the process still exists. */
1963             if (n > 0)
1964               {
1965 #ifndef PID_BINARY
1966                 hdb_lock_buffer[n] = '\0';
1967                 sscanf (hdb_lock_buffer, " %d", &pid);
1968 #else
1969                 pid = ((int *) hdb_lock_buffer)[0];
1970 #endif
1971                 if (pid == 0 || (kill(pid, 0) == -1 && errno == ESRCH))
1972                   {
1973                     n = 0;
1974                   }
1975               }
1976
1977             /* If the process does not exist then try to remove the lock */
1978             if (n == 0 && unlink (lock_file) == 0)
1979               {
1980                 syslog (LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1981                         dev, pid);
1982                 continue;
1983               }
1984
1985             syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, pid);
1986             break;
1987           }
1988
1989         syslog(LOG_ERR, "Can't create lock file %s: %m(%d)", lock_file, errno);
1990         break;
1991       }
1992
1993     free(lock_file);
1994     lock_file = NULL;
1995     return -1;
1996 }
1997
1998
1999 /********************************************************************
2000  *
2001  * unlock - remove our lockfile
2002  */
2003
2004 void unlock(void)
2005   {
2006     if (lock_file)
2007       {
2008         unlink(lock_file);
2009         free(lock_file);
2010         lock_file = NULL;
2011       }
2012   }
2013
2014 /********************************************************************
2015  *
2016  * sifvjcomp - config tcp header compression
2017  */
2018
2019 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
2020   {
2021     u_int x = get_flags();
2022
2023     if (vjcomp)
2024       {
2025         if (ioctl (ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
2026           {
2027             if (! ok_error (errno))
2028               {
2029                 syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m(%d)", errno);
2030               }
2031             vjcomp = 0;
2032           }
2033       }
2034
2035     x = vjcomp  ? x | SC_COMP_TCP     : x &~ SC_COMP_TCP;
2036     x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
2037     set_flags (x);
2038
2039     return 1;
2040   }
2041
2042 /********************************************************************
2043  *
2044  * sifup - Config the interface up and enable IP packets to pass.
2045  */
2046
2047 int sifup (int u)
2048   {
2049     struct ifreq ifr;
2050
2051     memset (&ifr, '\0', sizeof (ifr));
2052     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2053     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
2054       {
2055         if (! ok_error (errno))
2056           {
2057             syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m(%d)", errno);
2058           }
2059         return 0;
2060       }
2061
2062     ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
2063     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
2064       {
2065         if (! ok_error (errno))
2066           {
2067             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m(%d)", errno);
2068           }
2069         return 0;
2070       }
2071     if_is_up = 1;
2072     return 1;
2073   }
2074
2075 /********************************************************************
2076  *
2077  * sifdown - Config the interface down and disable IP.
2078  */
2079
2080 int sifdown (int u)
2081   {
2082     struct ifreq ifr;
2083
2084     if_is_up = 0;
2085
2086     memset (&ifr, '\0', sizeof (ifr));
2087     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2088     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
2089       {
2090         if (! ok_error (errno))
2091           {
2092             syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m(%d)", errno);
2093           }
2094         return 0;
2095       }
2096
2097     ifr.ifr_flags &= ~IFF_UP;
2098     ifr.ifr_flags |= IFF_POINTOPOINT;
2099     if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
2100       {
2101         if (! ok_error (errno))
2102           {
2103             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m(%d)", errno);
2104           }
2105         return 0;
2106       }
2107     return 1;
2108   }
2109
2110 /********************************************************************
2111  *
2112  * sifaddr - Config the interface IP addresses and netmask.
2113  */
2114
2115 int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
2116              u_int32_t net_mask)
2117   {
2118     struct ifreq   ifr; 
2119     struct rtentry rt;
2120     
2121     memset (&ifr, '\0', sizeof (ifr));
2122     memset (&rt,  '\0', sizeof (rt));
2123     
2124     SET_SA_FAMILY (ifr.ifr_addr,    AF_INET); 
2125     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); 
2126     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); 
2127
2128     strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
2129 /*
2130  *  Set our IP address
2131  */
2132     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
2133     if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
2134       {
2135         if (errno != EEXIST)
2136           {
2137             if (! ok_error (errno))
2138               {
2139                 syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m(%d)", errno);
2140               }
2141           }
2142         else
2143           {
2144             syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
2145           }
2146         return (0);
2147       } 
2148 /*
2149  *  Set the gateway address
2150  */
2151     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
2152     if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
2153       {
2154         if (! ok_error (errno))
2155           {
2156             syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m(%d)", errno); 
2157           }
2158         return (0);
2159       } 
2160 /*
2161  *  Set the netmask
2162  */
2163     if (net_mask != 0)
2164       {
2165         ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
2166         if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
2167           {
2168             if (! ok_error (errno))
2169               {
2170                 syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m(%d)", errno); 
2171               }
2172             return (0);
2173           } 
2174       }
2175 /*
2176  *  Add the device route
2177  */
2178     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2179     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2180     rt.rt_dev = ifname;  /* MJC */
2181
2182     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0L;
2183     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
2184     rt.rt_flags = RTF_UP | RTF_HOST;
2185
2186     if (ioctl(sock_fd, SIOCADDRT, &rt) < 0)
2187       {
2188         if (! ok_error (errno))
2189           {
2190             syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m(%d)", errno);
2191           }
2192         return (0);
2193       }
2194     return 1;
2195   }
2196
2197 /********************************************************************
2198  *
2199  * cifaddr - Clear the interface IP addresses, and delete routes
2200  * through the interface if possible.
2201  */
2202
2203 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
2204   {
2205     struct rtentry rt;
2206 /*
2207  *  Delete the route through the device
2208  */
2209     memset (&rt, '\0', sizeof (rt));
2210
2211     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
2212     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
2213     rt.rt_dev = ifname;  /* MJC */
2214
2215     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
2216     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
2217     rt.rt_flags = RTF_UP | RTF_HOST;
2218
2219     if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH)
2220       {
2221         if (still_ppp() && ! ok_error (errno))
2222           {
2223             syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m(%d)", errno);
2224           }
2225         return (0);
2226       }
2227     return 1;
2228   }
2229
2230 /********************************************************************
2231  *
2232  * open_loopback - open the device we use for getting packets
2233  * in demand mode.  Under Linux, we use our existing fd
2234  * to the ppp driver.
2235  */
2236 void
2237 open_ppp_loopback(void)
2238   {
2239     int            flags;
2240     struct termios tios;
2241
2242     if (openpty (&master_fd, &slave_fd, loop_name, NULL, NULL) < 0)
2243       {
2244         syslog(LOG_ERR, "No free pty for loopback");
2245         die(1);
2246       }
2247     SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
2248
2249     set_ppp_fd(slave_fd);
2250
2251     if (tcgetattr(ppp_fd, &tios) == 0)
2252       {
2253         tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
2254         tios.c_cflag |= CS8 | CREAD;
2255         tios.c_iflag  = IGNPAR | CLOCAL;
2256         tios.c_oflag  = 0;
2257         tios.c_lflag  = 0;
2258         if (tcsetattr(ppp_fd, TCSAFLUSH, &tios) < 0)
2259           {
2260             syslog(LOG_WARNING, "couldn't set attributes on loopback: %m(%d)", errno);
2261           }
2262       }
2263
2264     flags = fcntl(master_fd, F_GETFL);
2265     if (flags == -1 ||
2266         fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2267       {
2268         syslog(LOG_WARNING, "couldn't set master loopback to nonblock: %m(%d)", errno);
2269       }
2270
2271     flags = fcntl(ppp_fd, F_GETFL);
2272     if (flags == -1 ||
2273         fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
2274       {
2275         syslog(LOG_WARNING, "couldn't set slave loopback to nonblock: %m(%d)", errno);
2276       }
2277
2278     if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
2279       {
2280         syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
2281         die(1);
2282       }
2283 /*
2284  * Find out which interface we were given.
2285  */
2286     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
2287       { 
2288         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m(%d)", errno);
2289         die(1);
2290       }
2291 /*
2292  * Enable debug in the driver if requested.
2293  */
2294     set_kdebugflag (kdebugflag);
2295   }
2296
2297 /********************************************************************
2298  *
2299  * restore_loop - reattach the ppp unit to the loopback.
2300  *
2301  * The problem with the Linux variant is that the POSIX tty drivers will
2302  * sieze the line when it is disconnected. In addition, when the device
2303  * goes down all of the routes are deleted. This means that the tty needs
2304  * to be re-opened, reconfigured, and the device reconfigured and the routes
2305  * restored.
2306  */
2307
2308 void
2309 restore_loop(void)
2310   {
2311     int  x;
2312     int  fdflags;
2313     char fname [30];
2314 /*
2315  * Take down the existing interface
2316  */
2317     sifdown (0);
2318     (void) ioctl(ppp_fd, TIOCSETD, &tty_disc);
2319 /*
2320  * Find the existing flags. This works even if the tty has stolen the
2321  * line discipline.
2322  */
2323     fdflags = fcntl(ppp_fd, F_GETFL);
2324     if (fdflags < 0)
2325       {
2326         syslog (LOG_ERR, "retrieve file flags failed: %m(%d)", errno);
2327         fdflags = O_NONBLOCK | O_RDWR;
2328       }
2329 /*
2330  * Re-open the file so the we can re-establish the previous discipline
2331  */
2332     sprintf (fname, "/proc/self/fd/%d", ppp_fd);
2333     x = open (fname, O_RDWR | O_NONBLOCK, 0);
2334     if (x < 0)
2335       {
2336         syslog (LOG_ERR, "reopen of tty file failed: %m(%d)", errno);
2337       }
2338 /*
2339  * Transfer the newly opened file (to the same tty) back to the tty
2340  * file handle.
2341  */
2342     else
2343       {
2344         dup2 (x, ppp_fd);
2345         close (x);
2346         fcntl (ppp_fd, F_SETFL, fdflags);
2347         set_up_tty(ppp_fd, 0);
2348       }
2349 /*
2350  * Switch to the tty slave and put that into the PPP discipline.
2351  */
2352     set_ppp_fd(slave_fd);
2353
2354     if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
2355       {
2356         syslog(LOG_ERR, "ioctl(TIOCSETD): %m(%d)", errno);
2357         die(1);
2358       }
2359 /*
2360  * Fetch the current unit identifier.
2361  */
2362     if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
2363       { 
2364         syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m(%d)", errno);
2365         die(1);
2366       }
2367 /*
2368  * Restore the parameters for the PPP link.
2369  */
2370     ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
2371     ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
2372 /*
2373  * Reconfigure the IP addresses for the demand dial system.
2374  */
2375     (void) (ipcp_protent.demand_conf) (0);
2376   }
2377
2378 /********************************************************************
2379  *
2380  * sifnpmode - Set the mode for handling packets for a given NP.
2381  */
2382
2383 int
2384 sifnpmode(u, proto, mode)
2385     int u;
2386     int proto;
2387     enum NPmode mode;
2388 {
2389     struct npioctl npi;
2390
2391     npi.protocol = proto;
2392     npi.mode     = mode;
2393     if (ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0)
2394       {
2395         if (! ok_error (errno))
2396           {
2397             syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE, %d, %d): %m(%d)",
2398                    proto, mode, errno);
2399           }
2400         return 0;
2401       }
2402     return 1;
2403   }
2404
2405 \f
2406 #include <linux/ipx.h>
2407
2408 /********************************************************************
2409  *
2410  * sipxfaddr - Config the interface IPX networknumber
2411  */
2412
2413 int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
2414   {
2415     int    skfd; 
2416     int    result = 1;
2417     struct sockaddr_ipx  ipx_addr;
2418     struct ifreq         ifr;
2419     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2420
2421 #ifdef IPX_CHANGE
2422     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2423     if (skfd < 0)
2424       { 
2425         if (! ok_error (errno))
2426           {
2427             syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
2428           }
2429         result = 0;
2430       }
2431     else
2432       {
2433         memset (&ifr, '\0', sizeof (ifr));
2434         strcpy (ifr.ifr_name, ifname);
2435
2436         memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
2437         sipx->sipx_family  = AF_IPX;
2438         sipx->sipx_port    = 0;
2439         sipx->sipx_network = htonl (network);
2440         sipx->sipx_type    = IPX_FRAME_ETHERII;
2441         sipx->sipx_action  = IPX_CRTITF;
2442 /*
2443  *  Set the IPX device
2444  */
2445         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
2446           {
2447             result = 0;
2448             if (errno != EEXIST)
2449               {
2450                 if (! ok_error (errno))
2451                   {
2452                     syslog (LOG_DEBUG,
2453                             "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno);
2454                   }
2455               }
2456             else
2457               {
2458                 syslog (LOG_WARNING,
2459                         "ioctl(SIOCAIFADDR, CRTITF): Address already exists");
2460               }
2461           }
2462         close (skfd);
2463       }
2464 #endif
2465     return result;
2466   }
2467
2468 /********************************************************************
2469  *
2470  * cipxfaddr - Clear the information for the IPX network. The IPX routes
2471  *             are removed and the device is no longer able to pass IPX
2472  *             frames.
2473  */
2474
2475 int cipxfaddr (int unit)
2476   {
2477     int    skfd; 
2478     int    result = 1;
2479     struct sockaddr_ipx  ipx_addr;
2480     struct ifreq         ifr;
2481     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
2482
2483 #ifdef IPX_CHANGE
2484     skfd = socket (AF_IPX, SOCK_DGRAM, 0);
2485     if (skfd < 0)
2486       { 
2487         if (! ok_error (errno))
2488           {
2489             syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
2490           }
2491         result = 0;
2492       }
2493     else
2494       {
2495         memset (&ifr, '\0', sizeof (ifr));
2496         strcpy (ifr.ifr_name, ifname);
2497
2498         sipx->sipx_type    = IPX_FRAME_ETHERII;
2499         sipx->sipx_action  = IPX_DLTITF;
2500         sipx->sipx_family  = AF_IPX;
2501 /*
2502  *  Set the IPX device
2503  */
2504         if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
2505           {
2506             if (! ok_error (errno))
2507               {
2508                 syslog (LOG_INFO,
2509                         "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno);
2510               }
2511             result = 0;
2512           }
2513         close (skfd);
2514       }
2515 #endif
2516     return result;
2517   }
2518
2519 /********************************************************************
2520  *
2521  * sys_check_options - check the options that the user specified
2522  */
2523
2524 void
2525 sys_check_options(void)
2526   {
2527 #ifdef IPX_CHANGE
2528     struct stat stat_buf;
2529 /*
2530  * Disable the IPX protocol if the support is not present in the kernel.
2531  * If we disable it then ensure that IP support is enabled.
2532  */
2533     while (ipxcp_protent.enabled_flag)
2534       {
2535         if (path_to_procfs())
2536           {
2537             strcat (route_buffer, "/net/ipx_interface");
2538             if (lstat (route_buffer, &stat_buf) >= 0)
2539               {
2540                 break;
2541               }
2542           }
2543         syslog (LOG_ERR, "IPX support is not present in the kernel\n");
2544         ipxcp_protent.enabled_flag = 0;
2545         ipcp_protent.enabled_flag  = 1;
2546         break;
2547       }
2548 #endif
2549   }