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